package douyin import ( "context" "encoding/json" "fmt" "io" "net/http" "strings" "time" "bindbox-game/internal/service/sysconfig" ) const ( // AccessTokenURL Douyin access_token interface address AccessTokenURL = "https://developer.toutiao.com/api/apps/v2/token" ) // AccessTokenRequest request parameters type AccessTokenRequest struct { AppID string `json:"appid"` Secret string `json:"secret"` GrantType string `json:"grant_type"` } // AccessTokenResponse response type AccessTokenResponse struct { ErrNo int `json:"err_no"` ErrTips string `json:"err_tips"` Data struct { AccessToken string `json:"access_token"` ExpiresIn int `json:"expires_in"` } `json:"data"` } // GetAccessToken calls Douyin interface to get access_token func GetAccessToken(ctx context.Context) (string, error) { // Get Douyin config from dynamic config dynamicCfg := sysconfig.GetGlobalDynamicConfig() if dynamicCfg == nil { return "", fmt.Errorf("dynamic config service not initialized") } douyinCfg := dynamicCfg.GetDouyin(ctx) if douyinCfg.AppID == "" || douyinCfg.AppSecret == "" { return "", fmt.Errorf("Douyin mini program config incomplete") } reqBody := AccessTokenRequest{ AppID: douyinCfg.AppID, Secret: douyinCfg.AppSecret, GrantType: "client_credential", } jsonBody, err := json.Marshal(reqBody) if err != nil { return "", fmt.Errorf("failed to marshal request: %w", err) } // Send request httpClient := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequestWithContext(ctx, "POST", AccessTokenURL, strings.NewReader(string(jsonBody))) if err != nil { return "", fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Content-Type", "application/json") resp, err := httpClient.Do(req) if err != nil { return "", fmt.Errorf("failed to request Douyin interface: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("failed to read response: %w", err) } // Parse response var result AccessTokenResponse if err := json.Unmarshal(body, &result); err != nil { return "", fmt.Errorf("failed to parse response: %w, body: %s", err, string(body)) } if result.ErrNo != 0 { return "", fmt.Errorf("failed to get access_token: %s (code: %d)", result.ErrTips, result.ErrNo) } return result.Data.AccessToken, nil }