package qrcode import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "net/url" "time" "lone-services/pkg/utils" "lone-services/pkg/wechat/auth" ) // 小程序码(有数量限制):https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getQRCode.html const wxaCodeURL = "https://api.weixin.qq.com/wxa/getwxacode" // BuildPath 拼小程序 path,如 pagesB/userLogin/index?session_id=xxx func BuildPath(page string, params map[string]string) string { if len(params) == 0 { return page } query := url.Values{} for k, v := range params { query.Add(k, v) } return page + "?" + query.Encode() } // GetWxaCode 使用已有 access_token 生成有限小程序码,成功返回图片二进制。 func (c *Client) GetWxaCode(accessToken string, req *WxaCodeRequest) ([]byte, error) { if accessToken == utils.StringEmpty { return nil, fmt.Errorf("wechat access_token empty") } if req == nil || req.Path == utils.StringEmpty { return nil, fmt.Errorf("wechat qrcode path empty") } payload, err := json.Marshal(req) if err != nil { return nil, err } apiURL := fmt.Sprintf("%s?access_token=%s", wxaCodeURL, accessToken) httpClient := &http.Client{Timeout: 15 * time.Second} resp, err := httpClient.Post(apiURL, "application/json", bytes.NewReader(payload)) if err != nil { return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("wechat qrcode http status %d", resp.StatusCode) } if err := parseImageOrError(body); err != nil { return nil, err } return body, nil } // CreateWxaCode 通过 auth 拉取 access_token 后生成有限小程序码。 func (c *Client) CreateWxaCode(ctx context.Context, req *WxaCodeRequest) ([]byte, error) { token, err := auth.NewClient(c.AppID, c.Secret).AccessToken(ctx) if err != nil { return nil, err } return c.GetWxaCode(token.AccessToken, req) }