feat(api): 接入微信登录并原生实现咨询域(ECR-049/050)

小程序可在 Go 上完成微信手机号登录、测评、预约和下单,不再反代 Java。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-09-15 00:26:29 +08:00
co-authored by Cursor
parent db4d118f9a
commit 7155b8b53a
45 changed files with 3013 additions and 27 deletions
+84
View File
@@ -0,0 +1,84 @@
package wechat
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"time"
)
// Session is the jscode2session result.
type Session struct {
OpenID string
UnionID string
SessionKey string
}
// Client exchanges a mini-program js_code for a session.
type Client interface {
Code2Session(ctx context.Context, code string) (Session, error)
}
// APIClient calls api.weixin.qq.com.
type APIClient struct {
AppID string
Secret string
HTTP *http.Client
}
type wxSessionResp struct {
OpenID string `json:"openid"`
SessionKey string `json:"session_key"`
UnionID string `json:"unionid"`
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
}
// Enabled reports whether WeChat credentials are configured.
func (c *APIClient) Enabled() bool {
return c != nil && strings.TrimSpace(c.AppID) != "" && strings.TrimSpace(c.Secret) != ""
}
// Code2Session implements Client.
func (c *APIClient) Code2Session(ctx context.Context, code string) (Session, error) {
if !c.Enabled() {
return Session{}, errors.New("微信登录未配置")
}
code = strings.TrimSpace(code)
if code == "" {
return Session{}, errors.New("缺少微信登录码")
}
q := url.Values{}
q.Set("appid", c.AppID)
q.Set("secret", c.Secret)
q.Set("js_code", code)
q.Set("grant_type", "authorization_code")
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.weixin.qq.com/sns/jscode2session?"+q.Encode(), nil)
if err != nil {
return Session{}, err
}
cli := c.HTTP
if cli == nil {
cli = &http.Client{Timeout: 10 * time.Second}
}
resp, err := cli.Do(req)
if err != nil {
return Session{}, errors.New("微信服务暂不可用")
}
defer resp.Body.Close()
var body wxSessionResp
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
return Session{}, errors.New("微信服务暂不可用")
}
if body.ErrCode != 0 {
return Session{}, fmt.Errorf("微信登录失败(%d", body.ErrCode)
}
if body.OpenID == "" || body.SessionKey == "" {
return Session{}, errors.New("微信登录失败")
}
return Session{OpenID: body.OpenID, UnionID: body.UnionID, SessionKey: body.SessionKey}, nil
}