| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- package generic
- import (
- context2 "context"
- "net/url"
- "strings"
- "github.com/silenceper/wechat/v2/miniprogram/context"
- "github.com/silenceper/wechat/v2/util"
- )
- // defaultBaseURL 微信 API 默认基础地址
- const defaultBaseURL = "https://api.weixin.qq.com"
- // Generic 通用 API 调用,用于访问 SDK 尚未封装的小程序接口。
- // 支持自定义 path、query 参数、request body 以及 response 结构体。
- type Generic struct {
- *context.Context
- }
- // NewGeneric init
- func NewGeneric(ctx *context.Context) *Generic {
- return &Generic{ctx}
- }
- // BuildURL 构建完整请求 URL。
- // path 支持相对路径(如 "/intp/xxx")或完整 URL(如 "https://api.weixin.qq.com/intp/xxx")。
- // query 为额外的 URL 查询参数,可为 nil;access_token 会自动追加(若 query 中已包含则不重复追加)。
- func (g *Generic) BuildURL(path string, query url.Values) (string, error) {
- return g.BuildURLContext(context2.Background(), path, query)
- }
- // BuildURLContext 构建完整请求 URL(带 context)
- func (g *Generic) BuildURLContext(ctx context2.Context, path string, query url.Values) (string, error) {
- var baseURL string
- switch {
- case strings.HasPrefix(path, "http://"), strings.HasPrefix(path, "https://"):
- baseURL = path
- case strings.HasPrefix(path, "/"):
- baseURL = defaultBaseURL + path
- default:
- baseURL = defaultBaseURL + "/" + path
- }
- // 克隆 query,避免修改调用方原始值
- q := make(url.Values, len(query)+1)
- for k, v := range query {
- q[k] = v
- }
- // 自动追加 access_token
- if q.Get("access_token") == "" {
- accessToken, err := g.GetAccessTokenContext(ctx)
- if err != nil {
- return "", err
- }
- q.Set("access_token", accessToken)
- }
- sep := "?"
- if strings.Contains(baseURL, "?") {
- sep = "&"
- }
- return baseURL + sep + q.Encode(), nil
- }
- // Get 发送 GET 请求,返回原始响应字节。
- // 使用 util.DecodeWithError 可将响应解码到自定义结构体。
- func (g *Generic) Get(path string, query url.Values) (response []byte, err error) {
- return g.GetContext(context2.Background(), path, query)
- }
- // GetContext 发送 GET 请求(带 context),返回原始响应字节
- func (g *Generic) GetContext(ctx context2.Context, path string, query url.Values) (response []byte, err error) {
- var uri string
- if uri, err = g.BuildURLContext(ctx, path, query); err != nil {
- return
- }
- return util.HTTPGetContext(ctx, uri)
- }
- // PostJSON 发送 POST 请求(JSON body),返回原始响应字节。
- // body 可为 nil(无请求体);使用 util.DecodeWithError 可将响应解码到自定义结构体。
- func (g *Generic) PostJSON(path string, query url.Values, body interface{}) (response []byte, err error) {
- return g.PostJSONContext(context2.Background(), path, query, body)
- }
- // PostJSONContext 发送 POST 请求(JSON body,带 context),返回原始响应字节
- func (g *Generic) PostJSONContext(ctx context2.Context, path string, query url.Values, body interface{}) (response []byte, err error) {
- var uri string
- if uri, err = g.BuildURLContext(ctx, path, query); err != nil {
- return
- }
- return util.PostJSONContext(ctx, uri, body)
- }
- // GetDecode 发送 GET 请求并将响应解码到 resp。
- // resp 应为指向结构体的指针,结构体中可嵌入 util.CommonError 以自动校验错误码。
- // apiName 用于错误信息标识。
- func (g *Generic) GetDecode(path string, query url.Values, resp interface{}, apiName string) (err error) {
- return g.GetDecodeContext(context2.Background(), path, query, resp, apiName)
- }
- // GetDecodeContext 发送 GET 请求并将响应解码到 resp(带 context)
- func (g *Generic) GetDecodeContext(ctx context2.Context, path string, query url.Values, resp interface{}, apiName string) (err error) {
- var response []byte
- if response, err = g.GetContext(ctx, path, query); err != nil {
- return
- }
- return util.DecodeWithError(response, resp, apiName)
- }
- // PostJSONDecode 发送 POST 请求(JSON body)并将响应解码到 resp。
- // resp 应为指向结构体的指针,结构体中可嵌入 util.CommonError 以自动校验错误码。
- // apiName 用于错误信息标识。
- func (g *Generic) PostJSONDecode(path string, query url.Values, body, resp interface{}, apiName string) (err error) {
- return g.PostJSONDecodeContext(context2.Background(), path, query, body, resp, apiName)
- }
- // PostJSONDecodeContext 发送 POST 请求(JSON body)并将响应解码到 resp(带 context)
- func (g *Generic) PostJSONDecodeContext(ctx context2.Context, path string, query url.Values, body, resp interface{}, apiName string) (err error) {
- var response []byte
- if response, err = g.PostJSONContext(ctx, path, query, body); err != nil {
- return
- }
- return util.DecodeWithError(response, resp, apiName)
- }
|