95 lines
3.0 KiB
Go
95 lines
3.0 KiB
Go
package wechat
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
|
||
"bindbox-game/internal/pkg/httpclient"
|
||
)
|
||
|
||
// SchemeRequest 获取小程序 Scheme 码请求参数
|
||
type SchemeRequest struct {
|
||
JumpWxa JumpWxa `json:"jump_wxa,omitempty"`
|
||
IsExpire bool `json:"is_expire,omitempty"` // false:永久有效,true:到期失效
|
||
ExpireTime int64 `json:"expire_time,omitempty"` // 到期失效的 scheme 码的失效时间,为 Unix 时间戳
|
||
ExpireType int `json:"expire_type,omitempty"` // 失效时间类型,0-失效时间,1-失效间隔天数
|
||
ExpireInterval int `json:"expire_interval,omitempty"` // 失效间隔天数
|
||
}
|
||
|
||
type JumpWxa struct {
|
||
Path string `json:"path"`
|
||
Query string `json:"query"`
|
||
EnvVersion string `json:"env_version,omitempty"` // release, trial, develop
|
||
}
|
||
|
||
// SchemeResponse 获取小程序 Scheme 码响应
|
||
type SchemeResponse struct {
|
||
OpenLink string `json:"openlink"`
|
||
ErrCode int `json:"errcode"`
|
||
ErrMsg string `json:"errmsg"`
|
||
}
|
||
|
||
// GenerateScheme 获取小程序 Scheme 码
|
||
// path: 页面路径,如 "pages/index/index"
|
||
// query: 参数,如 "id=1" (可为空)
|
||
// envVersion: 要打开的小程序版本,默认 release
|
||
func GenerateScheme(accessToken string, path string, query string, envVersion string) (string, error) {
|
||
if accessToken == "" {
|
||
return "", fmt.Errorf("access_token 不能为空")
|
||
}
|
||
|
||
url := fmt.Sprintf("https://api.weixin.qq.com/wxa/generatescheme?access_token=%s", accessToken)
|
||
|
||
if envVersion == "" {
|
||
envVersion = "release"
|
||
}
|
||
|
||
reqBody := SchemeRequest{
|
||
JumpWxa: JumpWxa{
|
||
Path: path,
|
||
Query: query,
|
||
EnvVersion: envVersion,
|
||
},
|
||
IsExpire: false, // 默认生成永久有效的(注意:永久有效每天有上限,短期有效无上限但需设置过期)
|
||
// 如果需要生成短期,可以改为 true 并设置 ExpireInterval/ExpireTime
|
||
}
|
||
|
||
// 强制使用短期有效以避免消耗额度(如果需要)?
|
||
// 官方文档:永久有效 Scheme 每天上限 50w,短期无上限。
|
||
// 为了稳健,默认使用短期(30天)?或者让调用者决定。
|
||
// 这里先简单实现为默认短期(30天),避免额度问题。
|
||
reqBody.IsExpire = true
|
||
reqBody.ExpireType = 1
|
||
reqBody.ExpireInterval = 30
|
||
|
||
requestBody, err := json.Marshal(reqBody)
|
||
if err != nil {
|
||
return "", fmt.Errorf("序列化请求参数失败: %v", err)
|
||
}
|
||
|
||
resp, err := httpclient.GetHttpClient().R().
|
||
SetHeader("Content-Type", "application/json").
|
||
SetBody(requestBody).
|
||
Post(url)
|
||
|
||
if err != nil {
|
||
return "", fmt.Errorf("发送HTTP请求失败: %v", err)
|
||
}
|
||
|
||
if resp.StatusCode() != http.StatusOK {
|
||
return "", fmt.Errorf("HTTP请求失败,状态码: %d", resp.StatusCode())
|
||
}
|
||
|
||
var sResp SchemeResponse
|
||
if err := json.Unmarshal(resp.Body(), &sResp); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v", err)
|
||
}
|
||
|
||
if sResp.ErrCode != 0 {
|
||
return "", fmt.Errorf("获取Scheme失败: errcode=%d, errmsg=%s", sResp.ErrCode, sResp.ErrMsg)
|
||
}
|
||
|
||
return sResp.OpenLink, nil
|
||
}
|