first commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// Package wechat 封装微信小程序相关调用(此处为 code2session 实现)。
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"portal-mini-go/internal/pkg/errors"
|
||||
)
|
||||
|
||||
const code2SessionURL = "https://api.weixin.qq.com/sns/jscode2session"
|
||||
|
||||
// SessionInfo 是 code2session 返回的会话信息。
|
||||
type SessionInfo struct {
|
||||
OpenID string
|
||||
UnionID string
|
||||
SessionKey string
|
||||
}
|
||||
|
||||
// Client 微信调用客户端。凭证(appid/secret)由调用方按请求传入,
|
||||
// 不再依赖静态配置,方便后台动态纳管多个小程序。
|
||||
type Client struct {
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewClient() *Client {
|
||||
return &Client{client: &http.Client{}}
|
||||
}
|
||||
|
||||
// Code2Session 用 appID + secret + 登录 code 换取 openid / session_key。
|
||||
func (c *Client) Code2Session(ctx context.Context, appID, secret, code string) (*SessionInfo, error) {
|
||||
q := url.Values{}
|
||||
q.Set("appid", appID)
|
||||
q.Set("secret", secret)
|
||||
q.Set("js_code", code)
|
||||
q.Set("grant_type", "authorization_code")
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, code2SessionURL+"?"+q.Encode(), nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(50000, "build wechat request", err)
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(50000, "call wechat code2session", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(50000, "read wechat response", err)
|
||||
}
|
||||
|
||||
var r struct {
|
||||
OpenID string `json:"openid"`
|
||||
UnionID string `json:"unionid"`
|
||||
SessionKey string `json:"session_key"`
|
||||
ErrCode int `json:"errcode"`
|
||||
ErrMsg string `json:"errmsg"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &r); err != nil {
|
||||
return nil, errors.Wrap(50000, "decode wechat response", err)
|
||||
}
|
||||
if r.ErrCode != 0 {
|
||||
slog.Warn("wechat code2session error", slog.Int("errcode", r.ErrCode), slog.String("errmsg", r.ErrMsg))
|
||||
return nil, errors.Wrap(50000, fmt.Sprintf("wechat code2session: %s", r.ErrMsg), nil)
|
||||
}
|
||||
|
||||
return &SessionInfo{OpenID: r.OpenID, UnionID: r.UnionID, SessionKey: r.SessionKey}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user