diff --git a/service/alipayopen/alipay.system.oauth.token.go b/service/alipayopen/alipay.system.oauth.token.go new file mode 100644 index 00000000..bd53cc4d --- /dev/null +++ b/service/alipayopen/alipay.system.oauth.token.go @@ -0,0 +1,56 @@ +package alipayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" +) + +type AlipaySystemOauthTokenResponse struct { + AlipaySystemOauthTokenResponse struct { + AlipayUserId string `json:"alipay_user_id,omitempty"` + UserId string `json:"user_id"` // 支付宝用户的唯一标识。以2088开头的16位数字。 + AccessToken string `json:"access_token"` // 访问令牌。通过该令牌调用需要授权类接口 + ExpiresIn string `json:"expires_in"` // 访问令牌的有效时间,单位是秒。 + RefreshToken string `json:"refresh_token"` // 刷新令牌。通过该令牌可以刷新access_token + ReExpiresIn string `json:"re_expires_in"` // 刷新令牌的有效时间,单位是秒。 + AuthStart string `json:"auth_start"` // 授权token开始时间,作为有效期计算的起点 + } `json:"alipay_system_oauth_token_response"` +} + +type AlipaySystemOauthTokenResult struct { + Result AlipaySystemOauthTokenResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + ApiError ApiError // 接口错误 +} + +func newAlipaySystemOauthTokenResult(result AlipaySystemOauthTokenResponse, body []byte, http gorequest.Response, apiError ApiError) *AlipaySystemOauthTokenResult { + return &AlipaySystemOauthTokenResult{Result: result, Body: body, Http: http, ApiError: apiError} +} + +// AlipaySystemOauthToken 换取授权访问令牌 +// https://opendocs.alipay.com/open/02xtla +func (c *Client) AlipaySystemOauthToken(ctx context.Context, grantType, code, refreshToken string) (*AlipaySystemOauthTokenResult, error) { + // 参数 + params := gorequest.NewParams() + params.Set("grant_type", grantType) + if code != "" { + params.Set("code", code) + } + if refreshToken != "" { + params.Set("refresh_token", refreshToken) + } + // 请求 + request, err := c.request(ctx, c.newParamsWithType("alipay.system.oauth.token", params)) + if err != nil { + return nil, err + } + // 定义 + var response AlipaySystemOauthTokenResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newAlipaySystemOauthTokenResult(response, request.ResponseBody, request, apiError), err +} diff --git a/service/alipayopen/alipay.user.info.share.go b/service/alipayopen/alipay.user.info.share.go new file mode 100644 index 00000000..c14b113a --- /dev/null +++ b/service/alipayopen/alipay.user.info.share.go @@ -0,0 +1,50 @@ +package alipayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" +) + +type AlipayUserInfoShareResponse struct { + AlipayUserInfoShareResponse struct { + AlipayUserId string `json:"alipay_user_id,omitempty"` + UserId string `json:"user_id"` // 支付宝用户的唯一标识。以2088开头的16位数字。 + AccessToken string `json:"access_token"` // 访问令牌。通过该令牌调用需要授权类接口 + ExpiresIn string `json:"expires_in"` // 访问令牌的有效时间,单位是秒。 + RefreshToken string `json:"refresh_token"` // 刷新令牌。通过该令牌可以刷新access_token + ReExpiresIn string `json:"re_expires_in"` // 刷新令牌的有效时间,单位是秒。 + AuthStart string `json:"auth_start"` // 授权token开始时间,作为有效期计算的起点 + } `json:"alipay_system_oauth_token_response"` +} + +type AlipayUserInfoShareResult struct { + Result AlipayUserInfoShareResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + ApiError ApiError // 接口错误 +} + +func newAlipayUserInfoShareResult(result AlipayUserInfoShareResponse, body []byte, http gorequest.Response, apiError ApiError) *AlipayUserInfoShareResult { + return &AlipayUserInfoShareResult{Result: result, Body: body, Http: http, ApiError: apiError} +} + +// AlipayUserInfoShare 换取授权访问令牌 +// https://opendocs.alipay.com/open/02xtlb +func (c *Client) AlipayUserInfoShare(ctx context.Context, authToken string) (*AlipayUserInfoShareResult, error) { + // 参数 + params := gorequest.NewParams() + params.Set("auth_token", authToken) + // 请求 + request, err := c.request(ctx, c.newParamsWithType("alipay.user.info.share", params)) + if err != nil { + return nil, err + } + // 定义 + var response AlipayUserInfoShareResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newAlipayUserInfoShareResult(response, request.ResponseBody, request, apiError), err +} diff --git a/service/alipayopen/client.go b/service/alipayopen/client.go new file mode 100644 index 00000000..45cfe8d6 --- /dev/null +++ b/service/alipayopen/client.go @@ -0,0 +1,67 @@ +package alipayopen + +import ( + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "github.com/dtapps/go-library/utils/golog" + "github.com/dtapps/go-library/utils/gophp" + "github.com/dtapps/go-library/utils/gorequest" +) + +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string // 支付宝分配给开发者的应用ID + AppKey string // 支付宝分配给开发者的应用私钥 + AppRSA2 string // 应用公钥 + AlipayRSA2 string // 支付宝公钥 + Aes string // 接口内容加密方式 +} + +// Client 实例 +type Client struct { + requestClient *gorequest.App // 请求服务 + privateKey *rsa.PrivateKey // 私钥服务 + config struct { + appId string // 支付宝分配给开发者的应用ID + appKey string // 支付宝分配给开发者的应用私钥 + appRSA2 string // 应用公钥 + alipayRSA2 string // 支付宝公钥 + aes string // 接口内容加密方式 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } +} + +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { + + var err error + c := &Client{} + + c.config.appId = config.AppId + c.config.appKey = config.AppKey + c.config.appRSA2 = config.AppRSA2 + c.config.alipayRSA2 = config.AlipayRSA2 + c.config.aes = config.Aes + + // 私钥解码 + block, _ := pem.Decode([]byte("-----BEGIN RSA PRIVATE KEY-----\n" + gophp.ChunkSplit(config.AppKey, 64, "\n") + "-----END RSA PRIVATE KEY-----\n")) + if block == nil { + return nil, errors.New("签名私钥解码错误") + } + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + return nil, err + } + c.privateKey = privateKey.(*rsa.PrivateKey) + + // 请求 + c.requestClient = gorequest.NewHttp() + c.requestClient.Uri = apiUrl + + return c, nil +} diff --git a/service/alipayopen/config.go b/service/alipayopen/config.go new file mode 100644 index 00000000..818b43c2 --- /dev/null +++ b/service/alipayopen/config.go @@ -0,0 +1,12 @@ +package alipayopen + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/alipayopen/const.go b/service/alipayopen/const.go new file mode 100644 index 00000000..5e22650c --- /dev/null +++ b/service/alipayopen/const.go @@ -0,0 +1,22 @@ +package alipayopen + +const ( + apiUrl = "https://openapi.alipay.com/gateway.do" +) + +const ( + LogTable = "alipayopen" +) + +const AuthorizationCode = "authorization_code" // 表示换取使用用户授权码code换取授权令牌 +const RefreshToken = "refresh_token" // 表示使用refresh_token刷新获取新授权令牌 + +type ApiError struct { + ErrorResponse struct { + Code string `json:"code"` + Msg string `json:"msg"` + SubCode string `json:"sub_code"` + SubMsg string `json:"sub_msg"` + } `json:"error_response"` + Sign string `json:"sign"` +} diff --git a/service/alipayopen/get.go b/service/alipayopen/get.go new file mode 100644 index 00000000..9fd370b7 --- /dev/null +++ b/service/alipayopen/get.go @@ -0,0 +1,27 @@ +package alipayopen + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetAppId() string { + return c.config.appId +} + +func (c *Client) GetAppKey() string { + return c.config.appKey +} + +func (c *Client) GetAppRSA2() string { + return c.config.appRSA2 +} + +func (c *Client) GetAlipayRSA2() string { + return c.config.alipayRSA2 +} + +func (c *Client) GetAes() string { + return c.config.aes +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/alipayopen/params.go b/service/alipayopen/params.go new file mode 100644 index 00000000..e903a0a5 --- /dev/null +++ b/service/alipayopen/params.go @@ -0,0 +1,18 @@ +package alipayopen + +import ( + "github.com/dtapps/go-library/utils/gorequest" + "github.com/dtapps/go-library/utils/gotime" +) + +func (c *Client) newParamsWithType(_method string, param ...gorequest.Params) gorequest.Params { + params := gorequest.NewParamsWith(param...) + params.Set("app_id", c.GetAppId()) + params.Set("method", _method) + params.Set("format", "JSON") + params.Set("charset", "utf-8") + params.Set("sign_type", "RSA2") + params.Set("timestamp", gotime.Current().SetFormat(gotime.DateTimeFormat)) + params.Set("version", "1.0") + return params +} diff --git a/service/alipayopen/request.go b/service/alipayopen/request.go new file mode 100644 index 00000000..2a2e2fff --- /dev/null +++ b/service/alipayopen/request.go @@ -0,0 +1,39 @@ +package alipayopen + +import ( + "context" + "github.com/dtapps/go-library" + "github.com/dtapps/go-library/utils/gorequest" + "github.com/dtapps/go-library/utils/gostring" +) + +func (c *Client) request(ctx context.Context, param map[string]interface{}) (gorequest.Response, error) { + + // 签名 + params := c.sign(ctx, param) + + // 创建请求 + client := c.requestClient + + // 设置参数 + client.SetParams(params) + + // 设置用户代理 + client.SetUserAgent(gorequest.GetRandomUserAgentSystem()) + + // 传入SDk版本 + client.AfferentSdkUserVersion(go_library.Version()) + + // 发起请求 + request, err := client.Get(ctx) + if err != nil { + return gorequest.Response{}, err + } + + // 记录日志 + if c.log.status { + go c.log.client.MiddlewareCustom(ctx, gostring.ToString(params["method"]), request, go_library.Version()) + } + + return request, err +} diff --git a/service/alipayopen/sign.go b/service/alipayopen/sign.go new file mode 100644 index 00000000..b05cce9a --- /dev/null +++ b/service/alipayopen/sign.go @@ -0,0 +1,76 @@ +package alipayopen + +import ( + "context" + "crypto" + "crypto/rand" + "encoding/base64" + "encoding/json" + "fmt" + "github.com/dtapps/go-library/utils/gorequest" + "log" + "sort" + "strconv" + "strings" +) + +func (c *Client) rsaSign(signContent string, hash crypto.Hash) (string, error) { + + shaNew := hash.New() + shaNew.Write([]byte(signContent)) + hashed := shaNew.Sum(nil) + + signByte, err := c.privateKey.Sign(rand.Reader, hashed, crypto.SHA256) + if err != nil { + return "", err + } + + sign := base64.StdEncoding.EncodeToString(signByte) + + return sign, nil +} + +func (c *Client) sign(ctx context.Context, params gorequest.Params) gorequest.Params { + // 排序 + var keys []string + for key := range params { + keys = append(keys, key) + } + sort.Strings(keys) + + // 转换成字符串 + var signStr = "" + for _, key := range keys { + if key != "" { + signStr += fmt.Sprintf("%s=%s&", key, c.getString(params[key])) + } + } + + signStr = strings.TrimRight(signStr, "&") + + // 签名 + sign, err := c.rsaSign(signStr, crypto.SHA256) + if err != nil { + log.Printf("签名失败:%s\n", err) + return nil + } + params.Set("sign", sign) + + return params +} + +func (c *Client) getString(i interface{}) string { + switch v := i.(type) { + case string: + return v + case []byte: + return string(v) + case int: + return strconv.Itoa(v) + case bool: + return strconv.FormatBool(v) + default: + bytes, _ := json.Marshal(v) + return string(bytes) + } +} diff --git a/service/dingdanxia/client.go b/service/dingdanxia/client.go index 78227b6f..6103c45c 100644 --- a/service/dingdanxia/client.go +++ b/service/dingdanxia/client.go @@ -1,51 +1,35 @@ package dingdanxia import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - ApiKey string // 密钥 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + ApiKey string // 密钥 } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + apiKey string // 密钥 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.apiKey = config.ApiKey - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/dingdanxia/config.go b/service/dingdanxia/config.go new file mode 100644 index 00000000..6a5065bc --- /dev/null +++ b/service/dingdanxia/config.go @@ -0,0 +1,12 @@ +package dingdanxia + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/dingdanxia/const.go b/service/dingdanxia/const.go index f6917e99..5401c901 100644 --- a/service/dingdanxia/const.go +++ b/service/dingdanxia/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "dingdanxia" + LogTable = "dingdanxia" ) diff --git a/service/dingdanxia/get.go b/service/dingdanxia/get.go new file mode 100644 index 00000000..6e8229bc --- /dev/null +++ b/service/dingdanxia/get.go @@ -0,0 +1,11 @@ +package dingdanxia + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetApiKey() string { + return c.config.apiKey +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/dingdanxia/request.go b/service/dingdanxia/request.go index 2571563d..16018f9f 100644 --- a/service/dingdanxia/request.go +++ b/service/dingdanxia/request.go @@ -10,10 +10,10 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 公共参数 - params["apikey"] = c.config.ApiKey + params["apikey"] = c.GetApiKey() // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -27,18 +27,18 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置参数 client.SetParams(params) + // 传入SDk版本 + client.AfferentSdkUserVersion(go_library.Version()) + // 发起请求 request, err := client.Request(ctx) if err != nil { return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/dingdanxia/tbk.activityinfo.go b/service/dingdanxia/tbk.activityinfo.go new file mode 100644 index 00000000..1a1cdd7f --- /dev/null +++ b/service/dingdanxia/tbk.activityinfo.go @@ -0,0 +1,50 @@ +package dingdanxia + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type TbkActivityinfoResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data struct { + ClickUrl string `json:"click_url"` + WxQrcodeUrl string `json:"wx_qrcode_url"` + ShortClickUrl string `json:"short_click_url"` + TerminalType string `json:"terminal_type"` + MaterialOssUrl string `json:"material_oss_url"` + PageName string `json:"page_name"` + PageStartTime string `json:"page_start_time"` + PageEndTime string `json:"page_end_time"` + WxMiniprogramPath string `json:"wx_miniprogram_path"` + Tpwd string `json:"tpwd"` + LongTpwd string `json:"long_tpwd"` + } `json:"data"` +} + +type TbkActivityinfoResult struct { + Result TbkActivityinfoResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newTbkActivityinfoResult(result TbkActivityinfoResponse, body []byte, http gorequest.Response, err error) *TbkActivityinfoResult { + return &TbkActivityinfoResult{Result: result, Body: body, Http: http, Err: err} +} + +// TbkActivityinfo 官方活动转链,饿了么/口碑活动转链 +// https://www.dingdanxia.com/doc/122/173 +func (c *Client) TbkActivityinfo(ctx context.Context, notMustParams ...gorequest.Params) *TbkActivityinfoResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + // 请求 + request, err := c.request(ctx, apiUrl+"/tbk/activityinfo", params, http.MethodPost) + // 定义 + var response TbkActivityinfoResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newTbkActivityinfoResult(response, request.ResponseBody, request, err) +} diff --git a/service/dingdanxia/waimai.meituan_generateLink.go b/service/dingdanxia/waimai.meituan_generateLink.go new file mode 100644 index 00000000..f65a74a8 --- /dev/null +++ b/service/dingdanxia/waimai.meituan_generateLink.go @@ -0,0 +1,39 @@ +package dingdanxia + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type WaiMaiMeituanGenerateLinkResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data struct{} `json:"data"` + MiniCode string `json:"miniCode"` // 小程序码地址 +} + +type WaiMaiMeituanGenerateLinkResult struct { + Result WaiMaiMeituanGenerateLinkResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newWaiMaiMeituanGenerateLinkResult(result WaiMaiMeituanGenerateLinkResponse, body []byte, http gorequest.Response, err error) *WaiMaiMeituanGenerateLinkResult { + return &WaiMaiMeituanGenerateLinkResult{Result: result, Body: body, Http: http, Err: err} +} + +// WaiMaiMeituanGenerateLink 美团外卖/闪购/酒店/优选CPS转链接口【推荐使用】 +// https://www.dingdanxia.com/doc/221/173 +func (c *Client) WaiMaiMeituanGenerateLink(ctx context.Context, notMustParams ...gorequest.Params) *WaiMaiMeituanGenerateLinkResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + // 请求 + request, err := c.request(ctx, apiUrl+"/waimai/meituan_generateLink", params, http.MethodPost) + // 定义 + var response WaiMaiMeituanGenerateLinkResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newWaiMaiMeituanGenerateLinkResult(response, request.ResponseBody, request, err) +} diff --git a/service/dingdanxia/waimai.meituan_orderid.go b/service/dingdanxia/waimai.meituan_orderid.go index fb9bec28..5e9dd771 100644 --- a/service/dingdanxia/waimai.meituan_orderid.go +++ b/service/dingdanxia/waimai.meituan_orderid.go @@ -12,27 +12,35 @@ type WaiMaiMeituanOrderIdResponse struct { Msg string `json:"msg"` Data struct { Order struct { - BusinessLine int `json:"businessLine"` - SubBusinessLine int `json:"subBusinessLine"` - ActId int `json:"actId"` - Quantity int `json:"quantity"` - OrderId string `json:"orderId"` - Paytime string `json:"paytime"` - ModTime string `json:"modTime"` - Payprice string `json:"payprice"` - Profit string `json:"profit"` - CpaProfit string `json:"cpaProfit"` - Sid string `json:"sid"` - Appkey string `json:"appkey"` - Smstitle string `json:"smstitle"` - Status int `json:"status"` - TradeTypeList []int `json:"tradeTypeList"` - RiskOrder interface{} `json:"riskOrder"` - Refundprofit interface{} `json:"refundprofit"` - CpaRefundProfit interface{} `json:"cpaRefundProfit"` - RefundInfoList interface{} `json:"refundInfoList"` - RefundProfitList interface{} `json:"refundProfitList"` - Extra interface{} `json:"extra"` + OrderId string `json:"orderId"` // 订单号 + Sid string `json:"sid"` // 合作方唯一标识 + Payprice string `json:"payprice"` // 订单用户实际支付金额 + Profit string `json:"profit"` // 订单预估返佣金额 + CpaProfit string `json:"cpaProfit"` // 订单预估cpa总收益(优选、话费券) + Smstitle string `json:"smstitle"` // 订单标题 + Status int `json:"status"` // 订单状态,外卖、话费、闪购、优选、酒店订单会返回该字段 1 已付款 8 已完成 9 已退款或风控 + TradeTypeList []int `json:"tradeTypeList"` // 订单的奖励类型 话费订单类型返回该字段 3 首购奖励 5 留存奖励 优选订单类型返回该字段 2 cps 3 首购奖励 + RiskOrder interface{} `json:"riskOrder"` // 0表示非风控订单,1表示风控订单 + Refundprofit interface{} `json:"refundprofit"` // 订单需要扣除的返佣金额,外卖、话费、闪购、优选、酒店订单若发生退款会返回该字段 + CpaRefundProfit interface{} `json:"cpaRefundProfit"` // 订单需要扣除的cpa返佣金额(优选、话费券) + RefundInfoList struct { + RefundPrice interface{} `json:"refundPrice"` // 订单实际退款金额,外卖、话费、闪购、优选、酒店订单若发生退款会返回该字段 + RefundTime interface{} `json:"refundTime"` // 订单退款时间,10位时间戳 + RefundType interface{} `json:"refundType"` // ALL_REFUND(1, "全部退"), PART_REFUND(2, "部分退"), RISK_REFUND(3, "风控退"); + } `json:"refundInfoList,omitempty"` // 退款列表 + RefundProfitList struct { // 退款佣金明细 + RefundProfit interface{} `json:"refundProfit"` // 退款佣金 + RefundFinishTime interface{} `json:"refundFinishTime"` // 佣金产生时间,10位时间戳 + Type interface{} `json:"type"` // 券订单: 1 流量订单: 2 首单: 3 复购: 4 留存: 5 二单: 6 唤起: 7 + } `json:"refundProfitList,omitempty"` + BusinessLine int `json:"businessLine"` + SubBusinessLine int `json:"subBusinessLine"` + ActId int `json:"actId"` + Quantity int `json:"quantity"` + Paytime string `json:"paytime"` + ModTime string `json:"modTime"` + Appkey string `json:"appkey"` + Extra interface{} `json:"extra"` } `json:"order"` } `json:"data"` } @@ -50,10 +58,14 @@ func newWaiMaiMeituanOrderIdResult(result WaiMaiMeituanOrderIdResponse, body []b // WaiMaiMeituanOrderId 美团联盟外卖/闪购/优选/酒店订单查询API(订单号版) // https://www.dingdanxia.com/doc/179/173 -func (c *Client) WaiMaiMeituanOrderId(ctx context.Context, orderId string) *WaiMaiMeituanOrderIdResult { +func (c *Client) WaiMaiMeituanOrderId(ctx context.Context, orderId string, Type int) *WaiMaiMeituanOrderIdResult { // 参数 param := gorequest.NewParams() - param.Set("order_id", orderId) + param.Set("orderid", orderId) // 订单号 + if Type <= 0 { + Type = 4 + } + param.Set("type", Type) // 2-酒店 4-外卖 6-闪购 8-优选 默认4 params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, apiUrl+"/waimai/meituan_orderid", params, http.MethodPost) diff --git a/service/dingdanxia/waimai.meituan_privilege.go b/service/dingdanxia/waimai.meituan_privilege.go index a5887211..0450333f 100644 --- a/service/dingdanxia/waimai.meituan_privilege.go +++ b/service/dingdanxia/waimai.meituan_privilege.go @@ -11,17 +11,17 @@ type WaiMaiMeituanPrivilegeResponse struct { Code int `json:"code"` Msg string `json:"msg"` Data struct { - H5 string `json:"h5"` - ShortH5 string `json:"short_h5"` - Deeplink string `json:"deeplink"` - H5Evoke string `json:"h5_evoke"` - Tkl string `json:"tkl"` + H5 string `json:"h5"` // H5 领券 + ShortH5 string `json:"short_h5"` // H5 领券短链接 + Deeplink string `json:"deeplink"` // Deeplink领券 + H5Evoke string `json:"h5_evoke"` // H5 内唤起页 + Qrcode string `json:"qrcode"` // 二维码海报图片路径 + Tkl string `json:"tkl"` // 团口令 WeAppInfo struct { - AppId string `json:"app_id"` - PagePath string `json:"page_path"` - MiniCode string `json:"miniCode"` - } `json:"we_app_info"` - Qrcode string `json:"qrcode"` + AppId string `json:"app_id"` // 小程序ID + PagePath string `json:"page_path"` // 小程序路径 + MiniCode string `json:"miniCode"` // 小程序码 + } `json:"we_app_info"` // 小程序信息 } `json:"data"` } @@ -38,12 +38,13 @@ func newWaiMaiMeituanPrivilegeResult(result WaiMaiMeituanPrivilegeResponse, body // WaiMaiMeituanPrivilege 美团外卖CPS推广API接口 // https://www.dingdanxia.com/doc/174/173 -func (c *Client) WaiMaiMeituanPrivilege(ctx context.Context, sid string, generateWeApp, qrcode bool) *WaiMaiMeituanPrivilegeResult { +func (c *Client) WaiMaiMeituanPrivilege(ctx context.Context, sid string, generateWeApp bool, channels int, qrcode bool) *WaiMaiMeituanPrivilegeResult { // 参数 param := gorequest.NewParams() - param.Set("sid", sid) - param.Set("generate_we_app", generateWeApp) - param.Set("qrcode", qrcode) + param.Set("sid", sid) // 渠道方用户唯一标识,渠道可自定义,长度不超过50,参数中不能包含dingdanxia,用于向用户返佣,支持小写字母和数字的格式,其它字符可能造成无法正常跟单 + param.Set("generate_we_app", generateWeApp) // 是否生成小程序推广信息 + param.Set("channels", channels) // 推广渠道 1-小程序推广,2-公众号推广,3-app推广,4-社群推广 默认1 ,请务必选择对应渠道推广,选择错误会影响佣金比例 + param.Set("qrcode", qrcode) // 二维码图片 params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, apiUrl+"/waimai/meituan_privilege", params, http.MethodPost) diff --git a/service/dingdanxia/waimai.meituan_sg_privilege.go b/service/dingdanxia/waimai.meituan_sg_privilege.go index 8036009f..ff441edc 100644 --- a/service/dingdanxia/waimai.meituan_sg_privilege.go +++ b/service/dingdanxia/waimai.meituan_sg_privilege.go @@ -11,16 +11,16 @@ type WaiMaiMeituanSgPrivilegeResponse struct { Code int `json:"code"` Msg string `json:"msg"` Data struct { - H5 string `json:"h5"` - Deeplink string `json:"deeplink"` - H5Evoke string `json:"h5_evoke"` - ShortH5 string `json:"short_h5"` + H5 string `json:"h5"` // H5 领券 + Deeplink string `json:"deeplink"` // Deeplink领券 + H5Evoke string `json:"h5_evoke"` // H5 内唤起页 + ShortH5 string `json:"short_h5"` // h5短连接 WeAppInfo struct { - AppId string `json:"app_id"` - PagePath string `json:"page_path"` - MiniCode string `json:"miniCode"` - } `json:"we_app_info"` - Qrcode string `json:"qrcode"` + AppId string `json:"app_id"` // 小程序ID + PagePath string `json:"page_path"` // 小程序路径 + MiniCode string `json:"miniCode"` // 小程序码 + } `json:"we_app_info"` // 小程序信息 + Qrcode string `json:"qrcode"` // 海报 } `json:"data"` } @@ -40,9 +40,9 @@ func newWaiMaiMeituanSgPrivilegeResult(result WaiMaiMeituanSgPrivilegeResponse, func (c *Client) WaiMaiMeituanSgPrivilege(ctx context.Context, sid string, generateWeApp, qrcode bool) *WaiMaiMeituanSgPrivilegeResult { // 参数 param := gorequest.NewParams() - param.Set("sid", sid) - param.Set("generate_we_app", generateWeApp) - param.Set("qrcode", qrcode) + param.Set("sid", sid) // 渠道方用户唯一标识,渠道可自定义,长度不超过50,参数中不能包含dingdanxia,用于向用户返佣,支持小写字母和数字的格式,其它字符可能造成无法正常跟单 + param.Set("generate_we_app", generateWeApp) // 是否生成小程序推广信息 + param.Set("qrcode", qrcode) // 是否生成二维码海报 params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, apiUrl+"/waimai/meituan_sg_privilege", params, http.MethodPost) diff --git a/service/dingdanxia/waimai.meituan_youxuan_goods.go b/service/dingdanxia/waimai.meituan_youxuan_goods.go new file mode 100644 index 00000000..40e8f45b --- /dev/null +++ b/service/dingdanxia/waimai.meituan_youxuan_goods.go @@ -0,0 +1,52 @@ +package dingdanxia + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type WaiMaiMeituanYouxuanGoodsResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data struct { + Total int64 `json:"total"` // 数据总量 + skuList []struct { + ItemId string `json:"itemId"` // 商品信息-宝贝 id skuid + Title string `json:"title"` // 商品信息-商品标题 + PictUrl string `json:"pictUrl"` // 商品信息-商品主图 + SmallImages []string `json:"smallImages"` // 商品信息-商品小图列表 + OriginPrice string `json:"originPrice"` // 原价(单位为元) + PromotionPrice string `json:"promotionPrice"` // 促销价(活动价格)秒杀价格 (单位为元) + ItemDeepLinkUrl string `json:"itemDeepLinkUrl"` // 宝贝的 deeplink 地址 + ItemMiddlePageLinkUrl string `json:"itemMiddlePageLinkUrl"` // 宝贝的中间页地址 + ItemWXLinkUrl string `json:"itemWXLinkUrl"` // 宝贝的微信小程序链接地址 + HotFlag bool `json:"hotFlag"` // 是否是热门商品 + } + } `json:"data"` +} + +type WaiMaiMeituanYouxuanGoodsResult struct { + Result WaiMaiMeituanYouxuanGoodsResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newWaiMaiMeituanYouxuanGoodsResult(result WaiMaiMeituanYouxuanGoodsResponse, body []byte, http gorequest.Response, err error) *WaiMaiMeituanYouxuanGoodsResult { + return &WaiMaiMeituanYouxuanGoodsResult{Result: result, Body: body, Http: http, Err: err} +} + +// WaiMaiMeituanYouxuanGoods 优选商品查询API【2022年1月17日暂停数据访问】 +// https://www.dingdanxia.com/doc/235/173 +func (c *Client) WaiMaiMeituanYouxuanGoods(ctx context.Context, notMustParams ...gorequest.Params) *WaiMaiMeituanYouxuanGoodsResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + // 请求 + request, err := c.request(ctx, apiUrl+"/waimai/meituan_youxuan_goods", params, http.MethodPost) + // 定义 + var response WaiMaiMeituanYouxuanGoodsResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newWaiMaiMeituanYouxuanGoodsResult(response, request.ResponseBody, request, err) +} diff --git a/service/dingtalk/client.go b/service/dingtalk/client.go index cdc4a267..3cf06868 100644 --- a/service/dingtalk/client.go +++ b/service/dingtalk/client.go @@ -1,52 +1,38 @@ package dingtalk import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - Secret string - AccessToken string - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + Secret string + AccessToken string } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + secret string + accessToken string + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.secret = config.Secret + c.config.accessToken = config.AccessToken - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/dingtalk/config.go b/service/dingtalk/config.go new file mode 100644 index 00000000..9fa5cb18 --- /dev/null +++ b/service/dingtalk/config.go @@ -0,0 +1,18 @@ +package dingtalk + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) Config(secret, accessToken string) *Client { + c.config.secret = secret + c.config.accessToken = accessToken + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/dingtalk/const.go b/service/dingtalk/const.go index e64597d3..94ff1a66 100644 --- a/service/dingtalk/const.go +++ b/service/dingtalk/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "dingtalk" + LogTable = "dingtalk" ) diff --git a/service/dingtalk/get.go b/service/dingtalk/get.go new file mode 100644 index 00000000..23a4eac4 --- /dev/null +++ b/service/dingtalk/get.go @@ -0,0 +1,15 @@ +package dingtalk + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetSecret() string { + return c.config.secret +} + +func (c *Client) GetAccessToken() string { + return c.config.accessToken +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/dingtalk/request.go b/service/dingtalk/request.go index 7e97a998..1f94b24f 100644 --- a/service/dingtalk/request.go +++ b/service/dingtalk/request.go @@ -9,7 +9,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -23,18 +23,18 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置参数 client.SetParams(params) + // 传入SDk版本 + client.AfferentSdkUserVersion(go_library.Version()) + // 发起请求 request, err := client.Request(ctx) if err != nil { return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/dingtalk/robot.send.go b/service/dingtalk/robot.send.go index e6d2177b..50a6f5e3 100644 --- a/service/dingtalk/robot.send.go +++ b/service/dingtalk/robot.send.go @@ -33,7 +33,7 @@ func (c *Client) RobotSend(ctx context.Context, notMustParams ...gorequest.Param // 时间 timestamp := time.Now().UnixNano() / 1e6 // 请求 - request, err := c.request(ctx, apiUrl+fmt.Sprintf("/robot/send?access_token=%s×tamp=%d&sign=%s", c.config.AccessToken, timestamp, c.sign(timestamp)), params, http.MethodPost) + request, err := c.request(ctx, apiUrl+fmt.Sprintf("/robot/send?access_token=%s×tamp=%d&sign=%s", c.GetAccessToken(), timestamp, c.sign(timestamp)), params, http.MethodPost) // 定义 var response RobotSendResponse err = json.Unmarshal(request.ResponseBody, &response) diff --git a/service/dingtalk/sign.go b/service/dingtalk/sign.go index 4c03b6e7..69a06bd9 100644 --- a/service/dingtalk/sign.go +++ b/service/dingtalk/sign.go @@ -8,8 +8,8 @@ import ( ) func (c *Client) sign(t int64) string { - secStr := fmt.Sprintf("%d\n%s", t, c.config.Secret) - hmac256 := hmac.New(sha256.New, []byte(c.config.Secret)) + secStr := fmt.Sprintf("%d\n%s", t, c.GetSecret()) + hmac256 := hmac.New(sha256.New, []byte(c.GetSecret())) hmac256.Write([]byte(secStr)) result := hmac256.Sum(nil) return base64.StdEncoding.EncodeToString(result) diff --git a/service/douyin/client.go b/service/douyin/client.go index 52e8bcce..740729e0 100644 --- a/service/douyin/client.go +++ b/service/douyin/client.go @@ -2,55 +2,36 @@ package douyin import ( "errors" - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" "net/http" "strings" ) -type ConfigClient struct { - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { } +// Client 实例 type Client struct { - ua string // 用户代理 - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + ua string // 用户代理 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1" + c.config.ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1" - c.client = gorequest.NewHttp() - - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/douyin/config.go b/service/douyin/config.go new file mode 100644 index 00000000..7eb09ad6 --- /dev/null +++ b/service/douyin/config.go @@ -0,0 +1,12 @@ +package douyin + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/douyin/const.go b/service/douyin/const.go index ccf67a43..3d99231e 100644 --- a/service/douyin/const.go +++ b/service/douyin/const.go @@ -1,5 +1,5 @@ package douyin const ( - logTable = "douyin" + LogTable = "douyin" ) diff --git a/service/douyin/get.go b/service/douyin/get.go new file mode 100644 index 00000000..105f1bc3 --- /dev/null +++ b/service/douyin/get.go @@ -0,0 +1,7 @@ +package douyin + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/douyin/request.go b/service/douyin/request.go index 42da6805..eaa2fd7c 100644 --- a/service/douyin/request.go +++ b/service/douyin/request.go @@ -9,7 +9,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -21,7 +21,7 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte client.SetContentTypeJson() // 设置用户代理 - client.SetUserAgent(c.ua) + client.SetUserAgent(c.config.ua) // 设置参数 client.SetParams(params) @@ -32,12 +32,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/eastiot/client.go b/service/eastiot/client.go index 579aa9e8..8dea099f 100644 --- a/service/eastiot/client.go +++ b/service/eastiot/client.go @@ -1,52 +1,38 @@ package eastiot import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppId string - ApiKey string - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string + ApiKey string } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appId string + apiKey string + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appId = config.AppId + c.config.apiKey = config.ApiKey - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/eastiot/config.go b/service/eastiot/config.go new file mode 100644 index 00000000..0e3ca8fa --- /dev/null +++ b/service/eastiot/config.go @@ -0,0 +1,12 @@ +package eastiot + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/eastiot/const.go b/service/eastiot/const.go index 59eb7ff4..f4567dd0 100644 --- a/service/eastiot/const.go +++ b/service/eastiot/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "eastiot" + LogTable = "eastiot" ) diff --git a/service/eastiot/get.go b/service/eastiot/get.go new file mode 100644 index 00000000..2ce94bcc --- /dev/null +++ b/service/eastiot/get.go @@ -0,0 +1,15 @@ +package eastiot + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetAppId() string { + return c.config.appId +} + +func (c *Client) GetApiKey() string { + return c.config.apiKey +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/eastiot/request.go b/service/eastiot/request.go index b7d9ebe4..df63b682 100644 --- a/service/eastiot/request.go +++ b/service/eastiot/request.go @@ -10,14 +10,14 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 公共参数 - params["appId"] = c.config.AppId + params["appId"] = c.GetAppId() params["timeStamp"] = time.Now().Unix() // 签名 params["sign"] = c.getSign(params) // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -37,12 +37,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/eastiot/sign.go b/service/eastiot/sign.go index e73f0e82..15377a61 100644 --- a/service/eastiot/sign.go +++ b/service/eastiot/sign.go @@ -18,7 +18,7 @@ func (c *Client) getSign(p map[string]interface{}) string { for _, key := range keys { signStr += fmt.Sprintf("%s=%s&", key, c.getString(p[key])) } - signStr += fmt.Sprintf("apiKey=%s", c.config.ApiKey) + signStr += fmt.Sprintf("apiKey=%s", c.GetApiKey()) return gomd5.ToUpper(signStr) } diff --git a/service/ejiaofei/check_cost.go b/service/ejiaofei/check_cost.go index 3048eef4..5dfa1f40 100644 --- a/service/ejiaofei/check_cost.go +++ b/service/ejiaofei/check_cost.go @@ -35,7 +35,7 @@ func (c *Client) CheckCost(ctx context.Context, orderId string) *CheckCostResult param.Set("orderid", orderId) params := gorequest.NewParamsWith(param) // 签名 - c.signStr = fmt.Sprintf("userid%vpwd%vorderid%v", c.getUserId(), c.getPwd(), orderId) + c.config.signStr = fmt.Sprintf("userid%vpwd%vorderid%v", c.GetUserId(), c.GetPwd(), orderId) // 请求 request, err := c.request(ctx, apiUrl+"/checkCost.do", params, http.MethodGet) // 定义 diff --git a/service/ejiaofei/chongzhi_jkorders.go b/service/ejiaofei/chongzhi_jkorders.go index 4e99e190..7e356041 100644 --- a/service/ejiaofei/chongzhi_jkorders.go +++ b/service/ejiaofei/chongzhi_jkorders.go @@ -46,7 +46,7 @@ func (c *Client) ChOngZhiJkOrders(ctx context.Context, orderID string, face int, param.Set("amount", 1) params := gorequest.NewParamsWith(param) // 签名 - c.signStr = fmt.Sprintf("userid%vpwd%vorderid%vface%vaccount%vamount1", c.getUserId(), c.getPwd(), orderID, face, account) + c.config.signStr = fmt.Sprintf("userid%vpwd%vorderid%vface%vaccount%vamount1", c.GetUserId(), c.GetPwd(), orderID, face, account) // 请求 request, err := c.request(ctx, apiUrl+"/chongzhi_jkorders.do", params, http.MethodGet) // 定义 diff --git a/service/ejiaofei/client.go b/service/ejiaofei/client.go index c898831b..a5562740 100644 --- a/service/ejiaofei/client.go +++ b/service/ejiaofei/client.go @@ -1,54 +1,42 @@ package ejiaofei import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - UserId string - Pwd string - Key string - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + UserId string + Pwd string + Key string } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - signStr string // 加密信息 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + userId string + pwd string + key string + signStr string // 需要签名的字符串 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.userId = config.UserId + c.config.pwd = config.Pwd + c.config.key = config.Key - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() - return c, err + return c, nil } diff --git a/service/ejiaofei/config.go b/service/ejiaofei/config.go new file mode 100644 index 00000000..50faab46 --- /dev/null +++ b/service/ejiaofei/config.go @@ -0,0 +1,12 @@ +package ejiaofei + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/ejiaofei/const.go b/service/ejiaofei/const.go index 21d25767..1db3d117 100644 --- a/service/ejiaofei/const.go +++ b/service/ejiaofei/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "ejiaofei" + LogTable = "ejiaofei" ) diff --git a/service/ejiaofei/get.go b/service/ejiaofei/get.go index 65f2e9fc..a95f564c 100644 --- a/service/ejiaofei/get.go +++ b/service/ejiaofei/get.go @@ -1,13 +1,19 @@ package ejiaofei -func (c *Client) getUserId() string { - return c.config.UserId +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetUserId() string { + return c.config.userId +} + +func (c *Client) GetPwd() string { + return c.config.pwd } -func (c *Client) getPwd() string { - return c.config.Pwd +func (c *Client) GetKey() string { + return c.config.key } -func (c *Client) getKey() string { - return c.config.Key +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/ejiaofei/gprs_chongzhi_advance.go b/service/ejiaofei/gprs_chongzhi_advance.go index 071844bd..d2eee62a 100644 --- a/service/ejiaofei/gprs_chongzhi_advance.go +++ b/service/ejiaofei/gprs_chongzhi_advance.go @@ -51,7 +51,7 @@ func (c *Client) GprsChOngZhiAdvance(ctx context.Context, notMustParams ...goreq // 参数 params := gorequest.NewParamsWith(notMustParams...) // 签名 - c.signStr = fmt.Sprintf("userid%vpwd%vorderid%vaccount%vgprs%varea%veffecttime%vvalidity%vtimes%v", c.getUserId(), c.getPwd(), params["orderid"], params["account"], params["gprs"], params["area"], params["effecttime"], params["validity"], params["times"]) + c.config.signStr = fmt.Sprintf("userid%vpwd%vorderid%vaccount%vgprs%varea%veffecttime%vvalidity%vtimes%v", c.GetUserId(), c.GetPwd(), params["orderid"], params["account"], params["gprs"], params["area"], params["effecttime"], params["validity"], params["times"]) // 请求 request, err := c.request(ctx, apiUrl+"/gprsChongzhiAdvance.do", params, http.MethodGet) // 定义 diff --git a/service/ejiaofei/money_jkuser.go b/service/ejiaofei/money_jkuser.go index 19dd4d75..13107494 100644 --- a/service/ejiaofei/money_jkuser.go +++ b/service/ejiaofei/money_jkuser.go @@ -29,7 +29,7 @@ func newMoneyJkUserResult(result MoneyJkUserResponse, body []byte, http goreques // MoneyJkUser 用户余额查询 func (c *Client) MoneyJkUser(ctx context.Context) *MoneyJkUserResult { // 签名 - c.signStr = fmt.Sprintf("userid%vpwd%v", c.getUserId(), c.getPwd()) + c.config.signStr = fmt.Sprintf("userid%vpwd%v", c.GetUserId(), c.GetPwd()) // 请求 request, err := c.request(ctx, apiUrl+"/money_jkuser.do", map[string]interface{}{}, http.MethodGet) // 定义 diff --git a/service/ejiaofei/query_jkorders.go b/service/ejiaofei/query_jkorders.go index 606811a1..490d56c4 100644 --- a/service/ejiaofei/query_jkorders.go +++ b/service/ejiaofei/query_jkorders.go @@ -41,7 +41,7 @@ func (c *Client) QueryJkOrders(ctx context.Context, orderId string) *QueryJkOrde param.Set("orderid", orderId) params := gorequest.NewParamsWith(param) // 签名 - c.signStr = fmt.Sprintf("userid%vpwd%vorderid%v", c.getUserId(), c.getPwd(), orderId) + c.config.signStr = fmt.Sprintf("userid%vpwd%vorderid%v", c.GetUserId(), c.GetPwd(), orderId) // 请求 request, err := c.request(ctx, apiUrl+"/query_jkorders.do", params, http.MethodGet) // 定义 diff --git a/service/ejiaofei/query_txproduct.go b/service/ejiaofei/query_txproduct.go index afe16492..e048661c 100644 --- a/service/ejiaofei/query_txproduct.go +++ b/service/ejiaofei/query_txproduct.go @@ -27,7 +27,7 @@ func newQueryTxProductResult(result QueryTxProductResponse, body []byte, http go // QueryTxProduct 可充值腾讯产品查询 func (c *Client) QueryTxProduct(ctx context.Context) *QueryTxProductResult { // 签名 - c.signStr = fmt.Sprintf("userid%vpwd%v", c.getUserId(), c.getPwd()) + c.config.signStr = fmt.Sprintf("userid%vpwd%v", c.GetUserId(), c.GetPwd()) // 请求 request, err := c.request(ctx, apiUrl+"/queryTXproduct.do", map[string]interface{}{}, http.MethodGet) // 定义 diff --git a/service/ejiaofei/request.go b/service/ejiaofei/request.go index 6d2559dc..480062e1 100644 --- a/service/ejiaofei/request.go +++ b/service/ejiaofei/request.go @@ -11,14 +11,14 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 公共参数 - params["userid"] = c.getUserId() - params["pwd"] = c.getPwd() + params["userid"] = c.GetUserId() + params["pwd"] = c.GetPwd() // 签名 - params["userkey"] = gomd5.ToUpper(fmt.Sprintf("%s%s", c.signStr, c.getKey())) + params["userkey"] = gomd5.ToUpper(fmt.Sprintf("%s%s", c.config.signStr, c.GetKey())) // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -38,12 +38,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddlewareXml(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddlewareXml(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.MiddlewareXml(ctx, request, go_library.Version()) } return request, err diff --git a/service/ejiaofei/txchongzhi.go b/service/ejiaofei/txchongzhi.go index d8ab0498..a417e28d 100644 --- a/service/ejiaofei/txchongzhi.go +++ b/service/ejiaofei/txchongzhi.go @@ -47,7 +47,7 @@ func (c *Client) TxChOngZhi(ctx context.Context, notMustParams ...gorequest.Para // 参数 params := gorequest.NewParamsWith(notMustParams...) // 签名 - c.signStr = fmt.Sprintf("userid%vpwd%vorderid%vaccount%vproductid%vamount%vip%vtimes%v", c.getUserId(), c.getPwd(), params["orderid"], params["account"], params["productid"], params["amount"], params["ip"], params["times"]) + c.config.signStr = fmt.Sprintf("userid%vpwd%vorderid%vaccount%vproductid%vamount%vip%vtimes%v", c.GetUserId(), c.GetPwd(), params["orderid"], params["account"], params["productid"], params["amount"], params["ip"], params["times"]) // 请求 request, err := c.request(ctx, apiUrl+"/txchongzhi.do", params, http.MethodGet) // 定义 diff --git a/service/feishu/client.go b/service/feishu/client.go index 77c2c7a5..fe954b05 100644 --- a/service/feishu/client.go +++ b/service/feishu/client.go @@ -1,51 +1,35 @@ package feishu import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - Key string - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + Key string } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + key string + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.key = config.Key - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/feishu/config.go b/service/feishu/config.go new file mode 100644 index 00000000..2a244852 --- /dev/null +++ b/service/feishu/config.go @@ -0,0 +1,17 @@ +package feishu + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) Config(key string) *Client { + c.config.key = key + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/feishu/const.go b/service/feishu/const.go index 2da355a3..e750776f 100644 --- a/service/feishu/const.go +++ b/service/feishu/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "feishu" + LogTable = "feishu" ) diff --git a/service/feishu/get.go b/service/feishu/get.go new file mode 100644 index 00000000..ac2caeb0 --- /dev/null +++ b/service/feishu/get.go @@ -0,0 +1,11 @@ +package feishu + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetKey() string { + return c.config.key +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/feishu/request.go b/service/feishu/request.go index c2b89358..19f39ae4 100644 --- a/service/feishu/request.go +++ b/service/feishu/request.go @@ -9,7 +9,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -20,18 +20,18 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置参数 client.SetParams(params) + // 传入SDk版本 + client.AfferentSdkUserVersion(go_library.Version()) + // 发起请求 request, err := client.Post(ctx) if err != nil { return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/feishu/webhook.go b/service/feishu/webhook.go index b2109f39..e2f6b301 100644 --- a/service/feishu/webhook.go +++ b/service/feishu/webhook.go @@ -31,7 +31,7 @@ func (c *Client) WebhookSend(ctx context.Context, notMustParams ...gorequest.Par // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 - request, err := c.request(ctx, apiUrl+fmt.Sprintf("/open-apis/bot/v2/hook/%s", c.config.Key), params) + request, err := c.request(ctx, apiUrl+fmt.Sprintf("/open-apis/bot/v2/hook/%s", c.GetKey()), params) // 定义 var response WebhookSendResponse err = json.Unmarshal(request.ResponseBody, &response) diff --git a/service/jd/client.go b/service/jd/client.go index c3eee5ec..e1f17670 100644 --- a/service/jd/client.go +++ b/service/jd/client.go @@ -1,80 +1,45 @@ package jd import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppKey string // 应用Key - SecretKey string // 密钥 - SiteId string // 网站ID/APP ID - PositionId string // 推广位id - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + AppKey string // 应用Key + SecretKey string // 密钥 + SiteId string // 网站ID/APP ID + PositionId string // 推广位id } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 -} - -func NewClient(config *ConfigClient) (*Client, error) { - - var err error - c := &Client{config: config} - - c.client = gorequest.NewHttp() - c.client.Uri = apiUrl - - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } + requestClient *gorequest.App // 请求服务 + config struct { + appKey string // 应用Key + secretKey string // 密钥 + siteId string // 网站ID/APP ID + positionId string // 推广位id } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 } - - return c, nil } -// GoodsPriceToInt64 商品券后价 -func (c *Client) GoodsPriceToInt64(LowestCouponPrice float64) int64 { - return int64(LowestCouponPrice * 100) -} +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { -// GoodsOriginalPriceToInt64 商品原价 -func (c *Client) GoodsOriginalPriceToInt64(Price float64) int64 { - return int64(Price * 100) -} + c := &Client{} -// CouponProportionToInt64 佣金比率 -func (c *Client) CouponProportionToInt64(CommissionShare float64) int64 { - return int64(CommissionShare * 10) -} + c.config.appKey = config.AppKey + c.config.secretKey = config.SecretKey + c.config.siteId = config.SiteId + c.config.positionId = config.PositionId -// CouponAmountToInt64 优惠券金额 -func (c *Client) CouponAmountToInt64(Commission float64) int64 { - return int64(Commission * 100) -} + c.requestClient = gorequest.NewHttp() + c.requestClient.Uri = apiUrl -// CommissionIntegralToInt64 佣金积分 -func (c *Client) CommissionIntegralToInt64(GoodsPrice, CouponProportion int64) int64 { - return (GoodsPrice * CouponProportion) / 1000 + return c, nil } diff --git a/service/jd/config.go b/service/jd/config.go new file mode 100644 index 00000000..cd57511a --- /dev/null +++ b/service/jd/config.go @@ -0,0 +1,12 @@ +package jd + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/jd/const.go b/service/jd/const.go index cb240eb2..37fc8f55 100644 --- a/service/jd/const.go +++ b/service/jd/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "jd" + LogTable = "jd" ) diff --git a/service/jd/get.go b/service/jd/get.go index 820928f6..aa947fc9 100644 --- a/service/jd/get.go +++ b/service/jd/get.go @@ -1,21 +1,27 @@ package jd +import "github.com/dtapps/go-library/utils/golog" + // GetAppKey 应用Key func (c *Client) GetAppKey() string { - return c.config.AppKey + return c.config.appKey } // GetSecretKey 密钥 func (c *Client) GetSecretKey() string { - return c.config.SecretKey + return c.config.secretKey } // GetSiteId 网站ID/APP ID func (c *Client) GetSiteId() string { - return c.config.SiteId + return c.config.siteId } // GetPositionId 推广位id func (c *Client) GetPositionId() string { - return c.config.PositionId + return c.config.positionId +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/jd/request.go b/service/jd/request.go index b98c692e..3d70f077 100644 --- a/service/jd/request.go +++ b/service/jd/request.go @@ -2,9 +2,9 @@ package jd import ( "context" + "fmt" "github.com/dtapps/go-library" "github.com/dtapps/go-library/utils/gorequest" - "github.com/dtapps/go-library/utils/gostring" ) // 请求接口 @@ -14,7 +14,7 @@ func (c *Client) request(ctx context.Context, params map[string]interface{}) (go c.Sign(params) // 创建请求 - client := c.client + client := c.requestClient // 设置格式 client.SetContentTypeForm() @@ -28,12 +28,9 @@ func (c *Client) request(ctx context.Context, params map[string]interface{}) (go return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddlewareCustom(ctx, gostring.ToString(params["method"]), request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddlewareCustom(ctx, gostring.ToString(params["method"]), request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.MiddlewareCustom(ctx, fmt.Sprintf("%s", params["method"]), request, go_library.Version()) } return request, err diff --git a/service/kashangwl/api.buy.go b/service/kashangwl/api.buy.go index b8d0bfa6..86255100 100644 --- a/service/kashangwl/api.buy.go +++ b/service/kashangwl/api.buy.go @@ -10,7 +10,7 @@ type ApiBuyResponse struct { Code string `json:"code"` Message string `json:"message"` Data struct { - OrderID int64 `json:"order_id"` // 订单号 + OrderId string `json:"order_id"` // 订单号 ProductPrice string `json:"product_price"` // 商品价格 TotalPrice string `json:"total_price"` // 总支付价格 RechargeUrl string `json:"recharge_url"` // 卡密充值网址 diff --git a/service/kashangwl/api.buy.notify.gin.go b/service/kashangwl/api.buy.notify.gin.go new file mode 100644 index 00000000..c0b525f2 --- /dev/null +++ b/service/kashangwl/api.buy.notify.gin.go @@ -0,0 +1,26 @@ +package kashangwl + +import ( + "context" + "github.com/gin-gonic/gin" +) + +// ResponseApiBuyNotifyGin 购买商品 - 回调通知 - 请求参数 +type ResponseApiBuyNotifyGin struct { + OrderId string `form:"order_id" json:"order_id" xml:"order_id" uri:"order_id" binding:"required"` // 订单编号 + OuterOrderId string `form:"outer_order_id" json:"outer_order_id" xml:"outer_order_id" uri:"outer_order_id" binding:"omitempty"` // 商户订单号 + ProductId int `form:"product_id" json:"product_id" xml:"product_id" uri:"product_id" binding:"omitempty"` // 商品编号 + Quantity int `form:"quantity" json:"quantity" xml:"quantity" uri:"quantity" binding:"required"` // 购买数量 + State int `form:"state" json:"state" xml:"state" uri:"state" binding:"required"` // 订单状态(100:等待发货,101:正在充值,200:交易成功,500:交易失败,501:未知状态) + StateInfo string `form:"state_info" json:"state_info" xml:"state_info" uri:"state_info" binding:"omitempty"` // 状态信息 + CreatedAt string `form:"created_at" json:"created_at" xml:"created_at" uri:"created_at" binding:"required"` // 购买数量 +} + +// ApiBuyNotifyGin 购买商品 - 回调通知 +// http://doc.cqmeihu.cn/sales/order-status-notify.html +func (c *Client) ApiBuyNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson ResponseApiBuyNotifyGin, err error) { + + err = ginCtx.ShouldBind(&validateJson) + + return validateJson, err +} diff --git a/service/kashangwl/api.order.go b/service/kashangwl/api.order.go index 35f728b4..4006f59a 100644 --- a/service/kashangwl/api.order.go +++ b/service/kashangwl/api.order.go @@ -10,17 +10,17 @@ type ApiOrderResponse struct { Code string `json:"code"` Message string `json:"message"` Data struct { - ID int64 `json:"id"` // 订单号 - ProductID int `json:"product_id"` // 商品编号 + Id string `json:"id"` // 订单号 + ProductId int `json:"product_id"` // 商品编号 ProductName string `json:"product_name"` // 商品名称 ProductType int `json:"product_type"` // 商品类型(1:充值,2:卡密,3:卡券,4:人工) ProductPrice string `json:"product_price"` // 售价 Quantity int `json:"quantity"` // 购买数量 TotalPrice string `json:"total_price"` // 总支付价格 RefundedAmount float64 `json:"refunded_amount"` // 已退款金额 - BuyerCustomerID int `json:"buyer_customer_id"` // 买家编号 + BuyerCustomerId int `json:"buyer_customer_id"` // 买家编号 BuyerCustomerName string `json:"buyer_customer_name"` // 买家名称 - SellerCustomerID int `json:"seller_customer_id"` // 卖家编号 + SellerCustomerId int `json:"seller_customer_id"` // 卖家编号 SellerCustomerName string `json:"seller_customer_name"` // 卖家名称 State int `json:"state"` // 订单状态(100:等待发货,101:正在充值,200:交易成功,500:交易失败,501:未知状态) CreatedAt string `json:"created_at"` // 下单时间 @@ -34,8 +34,8 @@ type ApiOrderResponse struct { No string `json:"no"` Password string `json:"password"` } `json:"cards"` //【卡密类订单】卡密 - RechargeParams string `json:"recharge_params"` //【充值类订单】 - OuterApiOrderID string `json:"outer_ApiOrder_id,omitempty"` // 外部订单号 + RechargeParams string `json:"recharge_params"` //【充值类订单】 + OuterOrderId string `json:"outer_order_id,omitempty"` // 外部订单号 } `json:"data"` } diff --git a/service/kashangwl/api.outer-order.go b/service/kashangwl/api.outer-order.go index e73d5b67..9f5d4a98 100644 --- a/service/kashangwl/api.outer-order.go +++ b/service/kashangwl/api.outer-order.go @@ -10,17 +10,17 @@ type ApiOuterOrderResponse struct { Code string `json:"code"` Message string `json:"message"` Data struct { - ID int64 `json:"id"` // 订单号 - ProductID int `json:"product_id"` // 商品编号 + Id string `json:"id"` // 订单号 + ProductId int `json:"product_id"` // 商品编号 ProductName string `json:"product_name"` // 商品名称 ProductType int `json:"product_type"` // 商品类型(1:充值,2:卡密,3:卡券,4:人工) ProductPrice string `json:"product_price"` // 售价 Quantity int `json:"quantity"` // 购买数量 TotalPrice string `json:"total_price"` // 总支付价格 RefundedAmount float64 `json:"refunded_amount"` // 已退款金额 - BuyerCustomerID int `json:"buyer_customer_id"` // 买家编号 + BuyerCustomerId int `json:"buyer_customer_id"` // 买家编号 BuyerCustomerName string `json:"buyer_customer_name"` // 买家名称 - SellerCustomerID int `json:"seller_customer_id"` // 卖家编号 + SellerCustomerId int `json:"seller_customer_id"` // 卖家编号 SellerCustomerName string `json:"seller_customer_name"` // 卖家名称 State int `json:"state"` // 订单状态(100:等待发货,101:正在充值,200:交易成功,500:交易失败,501:未知状态) CreatedAt string `json:"created_at"` // 下单时间 @@ -35,7 +35,7 @@ type ApiOuterOrderResponse struct { Password string `json:"password"` } `json:"cards"` //【卡密类订单】卡密 RechargeParams string `json:"recharge_params"` //【充值类订单】 - OuterOrderID string `json:"outer_order_id,omitempty"` // 外部订单号 + OuterOrderId string `json:"outer_order_id,omitempty"` // 外部订单号 } `json:"data"` } diff --git a/service/kashangwl/api.product.cache.go b/service/kashangwl/api.product.cache.go index dddab400..b8e6f011 100644 --- a/service/kashangwl/api.product.cache.go +++ b/service/kashangwl/api.product.cache.go @@ -12,12 +12,11 @@ type ApiProductCacheResponse struct { Code int `json:"code"` Message string `json:"message"` Data struct { - GoodsId string `json:"goods_id"` - ApiGoodsId int `json:"api_goods_id"` - GoodsName string `json:"goods_name"` - ClassificationName string `json:"classification_name"` - GoodsPrice float64 `json:"goods_price"` - PurchaseTips string `json:"purchase_tips"` + GoodsId uint `json:"goods_id"` + ApiGoodsId int64 `json:"api_goods_id"` + GoodsName string `json:"goods_name"` + GoodsPrice float64 `json:"goods_price"` + PurchaseTips string `json:"purchase_tips"` } `json:"data"` Time int `json:"time"` TraceId string `json:"trace_id"` @@ -38,8 +37,10 @@ func newApiProductCacheResult(result ApiProductCacheResponse, body []byte, http func (c *Client) ApiProductCache(ctx context.Context, productId int64) *ApiProductCacheResult { // 参数 params := gorequest.NewParams() + params.Set("customer_id", c.GetCustomerId()) + params.Set("product_id", productId) // 请求 - request, err := c.requestCache(ctx, fmt.Sprintf("%s/%d/goods_info/%d", apiUrlCache, c.GetCustomerId(), productId), params, http.MethodGet) + request, err := c.requestCache(ctx, fmt.Sprintf("%s/goods_info", apiUrlCache), params, http.MethodGet) // 定义 var response ApiProductCacheResponse err = json.Unmarshal(request.ResponseBody, &response) diff --git a/service/kashangwl/api.product.go b/service/kashangwl/api.product.go index f1b360de..59d0a8fe 100644 --- a/service/kashangwl/api.product.go +++ b/service/kashangwl/api.product.go @@ -10,17 +10,17 @@ type ApiProductResponse struct { Code string `json:"code"` Message string `json:"message"` Data struct { - Id int `json:"id"` // 商品编号 - ProductName string `json:"product_name"` // 商品名称 - Name string `json:"name"` // 规格名称 - Price float64 `json:"price"` // 售价 - ValidPurchasingQuantity string `json:"valid_purchasing_quantity"` // 合法的购买数量 - SuperiorCommissionsRate int `json:"superior_commissions_rate"` // 上级佣金比例 - Type int `json:"type"` // 商品类型(1:充值,2:卡密,3:卡券,4:人工) - SupplyState int `json:"supply_state"` // 库存状态(1:充足,2:断货) - StockState int `json:"stock_state"` // 状态(1:上架,2:维护,3:下架) - BanStartAt string `json:"ban_start_at"` // 禁售开始时间 - BanEndAt string `json:"ban_end_at"` // 禁售结束时间 + Id int `json:"id"` // 商品编号 + ProductName string `json:"product_name,omitempty"` // 商品名称 + Name string `json:"name"` // 规格名称 + Price string `json:"price"` // 售价 + ValidPurchasingQuantity string `json:"valid_purchasing_quantity"` // 合法的购买数量 + SuperiorCommissionsRate int `json:"superior_commissions_rate"` // 上级佣金比例 + Type int `json:"type"` // 商品类型(1:充值,2:卡密,3:卡券,4:人工) + SupplyState int `json:"supply_state"` // 库存状态(1:充足,2:断货) + StockState int `json:"stock_state"` // 状态(1:上架,2:维护,3:下架) + BanStartAt string `json:"ban_start_at,omitempty"` // 禁售开始时间 + BanEndAt string `json:"ban_end_at,omitempty"` // 禁售结束时间 } `json:"data"` } diff --git a/service/kashangwl/client.go b/service/kashangwl/client.go index 1dce43c5..4fe1d4c5 100644 --- a/service/kashangwl/client.go +++ b/service/kashangwl/client.go @@ -1,53 +1,38 @@ package kashangwl import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - CustomerId int // 商家编号 - CustomerKey string // 商家密钥 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + CustomerId int64 // 商家编号 + CustomerKey string // 商家密钥 } -// Client 卡商网服务 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + customerId int64 // 商家编号 + customerKey string // 商家密钥 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.customerId = config.CustomerId + c.config.customerKey = config.CustomerKey - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/kashangwl/config.go b/service/kashangwl/config.go new file mode 100644 index 00000000..6d2e2217 --- /dev/null +++ b/service/kashangwl/config.go @@ -0,0 +1,12 @@ +package kashangwl + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/kashangwl/const.go b/service/kashangwl/const.go index e3e13be8..41179d0b 100644 --- a/service/kashangwl/const.go +++ b/service/kashangwl/const.go @@ -14,5 +14,5 @@ const ( ) const ( - logTable = "kashangwl" + LogTable = "kashangwl" ) diff --git a/service/kashangwl/get.go b/service/kashangwl/get.go index 0577b3d3..01e10f86 100644 --- a/service/kashangwl/get.go +++ b/service/kashangwl/get.go @@ -1,9 +1,15 @@ package kashangwl -func (c *Client) GetCustomerId() int { - return c.config.CustomerId +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetCustomerId() int64 { + return c.config.customerId } func (c *Client) GetCustomerKey() string { - return c.config.CustomerKey + return c.config.customerKey +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/kashangwl/request.go b/service/kashangwl/request.go index 5e400954..ca6421a3 100644 --- a/service/kashangwl/request.go +++ b/service/kashangwl/request.go @@ -17,7 +17,7 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte params["sign"] = c.getSign(c.GetCustomerKey(), params) // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -25,6 +25,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置格式 client.SetContentTypeJson() + // 设置用户代理 + client.SetUserAgent(gorequest.GetRandomUserAgentSystem()) + // 设置参数 client.SetParams(params) @@ -35,11 +38,8 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte } // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err @@ -48,7 +48,7 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte func (c *Client) requestCache(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -59,6 +59,9 @@ func (c *Client) requestCache(ctx context.Context, url string, params map[string // 设置FORM格式 client.SetContentTypeJson() + // 设置用户代理 + client.SetUserAgent(gorequest.GetRandomUserAgentSystem()) + // 设置参数 client.SetParams(params) @@ -69,11 +72,8 @@ func (c *Client) requestCache(ctx context.Context, url string, params map[string } // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/kashangwl/set.go b/service/kashangwl/set.go new file mode 100644 index 00000000..5e127f2c --- /dev/null +++ b/service/kashangwl/set.go @@ -0,0 +1,13 @@ +package kashangwl + +type SetConfigConfig struct { + CustomerId int64 // 商家编号 + CustomerKey string // 商家密钥 +} + +// SetConfig 配置 +func (c *Client) SetConfig(config *SetConfigConfig) *Client { + c.config.customerId = config.CustomerId + c.config.customerKey = config.CustomerKey + return c +} diff --git a/service/kuaishou/client.go b/service/kuaishou/client.go index 855eb5f9..e4634891 100644 --- a/service/kuaishou/client.go +++ b/service/kuaishou/client.go @@ -1,60 +1,34 @@ package kuaishou import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { } +// Client 实例 type Client struct { - ua string - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + ua string // 用户代理 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { - - var err error - c := &Client{config: config} +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - c.ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36" + c := &Client{} - c.client = gorequest.NewHttp() - - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.config.ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36" - //if c.config.PgsqlDb != nil { - // go c.log.GormMiddleware(request) - //} - //if c.config.MongoDb != nil { - // go c.log.MongoMiddleware(request) - //} + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/kuaishou/cofnig.go b/service/kuaishou/cofnig.go new file mode 100644 index 00000000..63ae194f --- /dev/null +++ b/service/kuaishou/cofnig.go @@ -0,0 +1,12 @@ +package kuaishou + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/kuaishou/const.go b/service/kuaishou/const.go index bfe84605..b1e013b5 100644 --- a/service/kuaishou/const.go +++ b/service/kuaishou/const.go @@ -1,5 +1,5 @@ package kuaishou const ( - logTable = "kuaishou" + LogTable = "kuaishou" ) diff --git a/service/kuaishou/get.go b/service/kuaishou/get.go new file mode 100644 index 00000000..57779ed9 --- /dev/null +++ b/service/kuaishou/get.go @@ -0,0 +1,7 @@ +package kuaishou + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/meituan/api.generate_link.go b/service/meituan/api.generate_link.go index 73b42a98..e83d994f 100644 --- a/service/meituan/api.generate_link.go +++ b/service/meituan/api.generate_link.go @@ -29,14 +29,14 @@ func newApiGenerateLinkResult(result ApiGenerateLinkResponse, body []byte, http func (c *Client) ApiGenerateLink(ctx context.Context, actId int64, sid string, linkType, shortLink int) *ApiGenerateLinkResult { // 参数 param := gorequest.NewParams() - param.Set("actId", actId) // 活动id,可以在联盟活动列表中查看获取 - param.Set("appkey", c.config.AppKey) // 媒体名称,可在推广者备案-媒体管理中查询 - param.Set("sid", sid) // 推广位sid,支持通过接口自定义创建,不受平台200个上限限制,长度不能超过64个字符,支持小写字母和数字,历史已创建的推广位不受这个约束 - param.Set("linkType", linkType) // 投放链接的类型 - param.Set("shortLink", shortLink) // 获取长链还是短链 + param.Set("actId", actId) // 活动id,可以在联盟活动列表中查看获取 + param.Set("appkey", c.GetAppKey()) // 媒体名称,可在推广者备案-媒体管理中查询 + param.Set("sid", sid) // 推广位sid,支持通过接口自定义创建,不受平台200个上限限制,长度不能超过64个字符,支持小写字母和数字,历史已创建的推广位不受这个约束 + param.Set("linkType", linkType) // 投放链接的类型 + param.Set("shortLink", shortLink) // 获取长链还是短链 // 转换 params := gorequest.NewParamsWith(param) - params["sign"] = c.getSign(c.config.Secret, params) + params["sign"] = c.getSign(c.GetSecret(), params) // 请求 request, err := c.request(ctx, apiUrl+"/api/generateLink", params, http.MethodGet) // 定义 diff --git a/service/meituan/api.getqualityscorebysid.go b/service/meituan/api.getqualityscorebysid.go index 595bafc5..bb18cddf 100644 --- a/service/meituan/api.getqualityscorebysid.go +++ b/service/meituan/api.getqualityscorebysid.go @@ -40,8 +40,8 @@ func (c *Client) ApiGetQuaLitYsCoreBySid(ctx context.Context, notMustParams ...g params := gorequest.NewParamsWith(notMustParams...) // 请求时刻10位时间戳(秒级),有效期60s params["ts"] = gotime.Current().Timestamp() - params["appkey"] = c.config.AppKey - params["sign"] = c.getSign(c.config.Secret, params) + params["appkey"] = c.GetAppKey() + params["sign"] = c.getSign(c.GetSecret(), params) // 请求 request, err := c.request(ctx, apiUrl+"/api/getqualityscorebysid", params, http.MethodGet) // 定义 diff --git a/service/meituan/api.mini_code.go b/service/meituan/api.mini_code.go index 97a011bd..8fb0b68f 100644 --- a/service/meituan/api.mini_code.go +++ b/service/meituan/api.mini_code.go @@ -29,12 +29,12 @@ func newApiMiniCodeResult(result ApiMiniCodeResponse, body []byte, http goreques func (c *Client) ApiMiniCode(ctx context.Context, actId int64, sid string) *ApiMiniCodeResult { // 参数 param := gorequest.NewParams() - param.Set("appkey", c.config.AppKey) + param.Set("appkey", c.GetAppKey()) param.Set("sid", sid) param.Set("actId", actId) // 转换 params := gorequest.NewParamsWith(param) - params["sign"] = c.getSign(c.config.Secret, params) + params["sign"] = c.getSign(c.GetSecret(), params) // 请求 request, err := c.request(ctx, apiUrl+"/api/miniCode", params, http.MethodGet) // 定义 diff --git a/service/meituan/api.order.go b/service/meituan/api.order.go index 3850784e..ef3eeec9 100644 --- a/service/meituan/api.order.go +++ b/service/meituan/api.order.go @@ -52,8 +52,8 @@ func (c *Client) ApiOrder(ctx context.Context, notMustParams ...gorequest.Params // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求时刻10位时间戳(秒级),有效期60s - params["appkey"] = c.config.AppKey - params["sign"] = c.getSign(c.config.Secret, params) + params["appkey"] = c.GetAppKey() + params["sign"] = c.getSign(c.GetSecret(), params) // 请求 request, err := c.request(ctx, apiUrl+"/api/order", params, http.MethodGet) // 定义 diff --git a/service/meituan/api.order_list.go b/service/meituan/api.order_list.go index e4ff1a58..b3a11185 100644 --- a/service/meituan/api.order_list.go +++ b/service/meituan/api.order_list.go @@ -52,8 +52,8 @@ func (c *Client) ApiOrderList(ctx context.Context, notMustParams ...gorequest.Pa params := gorequest.NewParamsWith(notMustParams...) // 请求时刻10位时间戳(秒级),有效期60s params["ts"] = gotime.Current().Timestamp() - params["appkey"] = c.config.AppKey - params["sign"] = c.getSign(c.config.Secret, params) + params["appkey"] = c.GetAppKey() + params["sign"] = c.getSign(c.GetSecret(), params) // 请求 request, err := c.request(ctx, apiUrl+"/api/orderList", params, http.MethodGet) // 定义 diff --git a/service/meituan/client.go b/service/meituan/client.go index 1205f88a..3912f2b2 100644 --- a/service/meituan/client.go +++ b/service/meituan/client.go @@ -1,53 +1,38 @@ package meituan import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - Secret string // 秘钥 - AppKey string // 渠道标记 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + Secret string // 秘钥 + AppKey string // 渠道标记 } -// Client 美团联盟 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + secret string // 秘钥 + appKey string // 渠道标记 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.secret = config.Secret + c.config.appKey = config.AppKey - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/meituan/config.go b/service/meituan/config.go new file mode 100644 index 00000000..97b896e1 --- /dev/null +++ b/service/meituan/config.go @@ -0,0 +1,12 @@ +package meituan + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/meituan/const.go b/service/meituan/const.go index 11064683..0a870c0a 100644 --- a/service/meituan/const.go +++ b/service/meituan/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "meituan" + LogTable = "meituan" ) diff --git a/service/meituan/get.go b/service/meituan/get.go index e4e24d39..a56c3293 100644 --- a/service/meituan/get.go +++ b/service/meituan/get.go @@ -1,5 +1,15 @@ package meituan +import "github.com/dtapps/go-library/utils/golog" + func (c *Client) GetAppKey() string { - return c.config.AppKey + return c.config.appKey +} + +func (c *Client) GetSecret() string { + return c.config.secret +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/meituan/request.go b/service/meituan/request.go index c8f79f25..d2a96926 100644 --- a/service/meituan/request.go +++ b/service/meituan/request.go @@ -9,7 +9,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -30,11 +30,8 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte } // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/pinduoduo/client.go b/service/pinduoduo/client.go index 37f5425a..6ec6ff89 100644 --- a/service/pinduoduo/client.go +++ b/service/pinduoduo/client.go @@ -1,70 +1,51 @@ package pinduoduo import ( - "fmt" - "github.com/dtapps/go-library/utils/dorm" + "github.com/dtapps/go-library/utils/godecimal" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "github.com/dtapps/go-library/utils/gostring" - "gorm.io/gorm" - "regexp" - "strconv" "strings" ) -type ConfigClient struct { - ClientId string // POP分配给应用的client_id - ClientSecret string // POP分配给应用的client_secret - MediaId string // 媒体ID - Pid string // 推广位 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + ClientId string // POP分配给应用的client_id + ClientSecret string // POP分配给应用的client_secret + MediaId string // 媒体ID + Pid string // 推广位 } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + clientId string // POP分配给应用的client_id + clientSecret string // POP分配给应用的client_secret + mediaId string // 媒体ID + pid string // 推广位 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() - c.client.Uri = apiUrl + c.config.clientId = config.ClientId + c.config.clientSecret = config.ClientSecret + c.config.mediaId = config.MediaId + c.config.pid = config.Pid - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() + c.requestClient.Uri = apiUrl return c, nil } -func (c *Client) ConfigPid(pid string) *Client { - n := c - n.config.Pid = pid - return n -} - type ErrResp struct { ErrorResponse struct { ErrorMsg string `json:"error_msg"` @@ -81,28 +62,11 @@ type CustomParametersResult struct { } func (c *Client) SalesTipParseInt64(salesTip string) int64 { - parseInt, err := strconv.ParseInt(salesTip, 10, 64) - if err != nil { - salesTipStr := salesTip - if strings.Contains(salesTip, "万+") { - salesTipStr = strings.Replace(salesTip, "万+", "0000", -1) - } else if strings.Contains(salesTip, "万") { - salesTipStr = strings.Replace(salesTip, "万", "000", -1) - } - re := regexp.MustCompile("[0-9]+") - SalesTipMap := re.FindAllString(salesTipStr, -1) - if len(SalesTipMap) == 2 { - return gostring.ToInt64(fmt.Sprintf("%s%s", SalesTipMap[0], SalesTipMap[1])) - } else if len(SalesTipMap) == 1 { - return gostring.ToInt64(SalesTipMap[0]) - } else { - return 0 - } + if strings.Contains(salesTip, "万+") { + return godecimal.NewString(strings.Replace(salesTip, "万+", "0000", -1)).Int64() + } else if strings.Contains(salesTip, "万") { + return godecimal.NewString(strings.Replace(salesTip, "万", "000", -1)).Int64() } else { - return parseInt + return godecimal.NewString(salesTip).Int64() } } - -func (c *Client) CommissionIntegralToInt64(GoodsPrice, CouponProportion int64) int64 { - return (GoodsPrice * CouponProportion) / 1000 -} diff --git a/service/pinduoduo/config.go b/service/pinduoduo/config.go new file mode 100644 index 00000000..83ed1dcf --- /dev/null +++ b/service/pinduoduo/config.go @@ -0,0 +1,17 @@ +package pinduoduo + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) ConfigPid(pid string) *Client { + c.config.pid = pid + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/pinduoduo/const.go b/service/pinduoduo/const.go index 785d4241..5dd7c27a 100644 --- a/service/pinduoduo/const.go +++ b/service/pinduoduo/const.go @@ -5,5 +5,15 @@ const ( ) const ( - logTable = "pinduoduo" + LogTable = "pinduoduo" ) + +type ApiErrorT struct { + ErrorResponse struct { + ErrorMsg string `json:"error_msg"` + SubMsg string `json:"sub_msg"` + SubCode string `json:"sub_code"` + ErrorCode int `json:"error_code"` + RequestId string `json:"request_id"` + } `json:"error_response"` +} diff --git a/service/pinduoduo/get.go b/service/pinduoduo/get.go new file mode 100644 index 00000000..8991ec30 --- /dev/null +++ b/service/pinduoduo/get.go @@ -0,0 +1,23 @@ +package pinduoduo + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetClientId() string { + return c.config.clientId +} + +func (c *Client) GetClientSecret() string { + return c.config.clientSecret +} + +func (c *Client) GetMediaId() string { + return c.config.mediaId +} + +func (c *Client) GetPid() string { + return c.config.pid +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/pinduoduo/params.go b/service/pinduoduo/params.go index 4ac10f83..86fe6470 100644 --- a/service/pinduoduo/params.go +++ b/service/pinduoduo/params.go @@ -27,18 +27,18 @@ func NewParamsWithType(_type string, params ...Params) Params { } func (c *Client) Sign(p Params) { - p["client_id"] = c.config.ClientId + p["client_id"] = c.GetClientId() // 排序所有的 key var keys []string for key := range p { keys = append(keys, key) } sort.Strings(keys) - signStr := c.config.ClientSecret + signStr := c.GetClientSecret() for _, key := range keys { signStr += key + getString(p[key]) } - signStr += c.config.ClientSecret + signStr += c.GetClientSecret() p["sign"] = createSign(signStr) } diff --git a/service/pinduoduo/pdd.ddk.cms.prom.url.generate.go b/service/pinduoduo/pdd.ddk.cms.prom.url.generate.go index a0552761..2ce2b3d2 100644 --- a/service/pinduoduo/pdd.ddk.cms.prom.url.generate.go +++ b/service/pinduoduo/pdd.ddk.cms.prom.url.generate.go @@ -66,7 +66,7 @@ func newCmsPromUrlGenerateResult(result CmsPromUrlGenerateResponse, body []byte, func (c *Client) CmsPromUrlGenerate(ctx context.Context, notMustParams ...Params) *CmsPromUrlGenerateResult { // 参数 params := NewParamsWithType("pdd.ddk.cms.prom.url.generate", notMustParams...) - params.Set("p_id_list", []string{c.config.Pid}) + params.Set("p_id_list", []string{c.GetPid()}) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.goods.detail.go b/service/pinduoduo/pdd.ddk.goods.detail.go index ddbb0b76..06ee0c1b 100644 --- a/service/pinduoduo/pdd.ddk.goods.detail.go +++ b/service/pinduoduo/pdd.ddk.goods.detail.go @@ -101,7 +101,7 @@ func newGoodsDetailResult(result GoodsDetailResponse, body []byte, http goreques func (c *Client) GoodsDetail(ctx context.Context, notMustParams ...Params) *GoodsDetailResult { // 参数 params := NewParamsWithType("pdd.ddk.goods.detail", notMustParams...) - params.Set("pid", c.config.Pid) + params.Set("pid", c.GetPid()) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.goods.promotion.url.generate.go b/service/pinduoduo/pdd.ddk.goods.promotion.url.generate.go index c2cccccf..40d1bf8d 100644 --- a/service/pinduoduo/pdd.ddk.goods.promotion.url.generate.go +++ b/service/pinduoduo/pdd.ddk.goods.promotion.url.generate.go @@ -34,6 +34,11 @@ type GoodsPromotionUrlGenerateResponse struct { UserName string `json:"user_name,omitempty"` // 用户名 WeAppIconUrl string `json:"we_app_icon_url,omitempty"` // 小程序图片 } `json:"we_app_info"` + WeixinCode string `json:"weixin_code"` + WeAppWebViewUrl string `json:"we_app_web_view_url"` + WeAppWebViewShortUrl string `json:"we_app_web_view_short_url"` + TzSchemaUrl string `json:"tz_schema_url"` + WeixinShortLink string `json:"weixin_short_link"` } `json:"goods_promotion_url_list"` } `json:"goods_promotion_url_generate_response"` } @@ -54,7 +59,7 @@ func newGoodsPromotionUrlGenerateResult(result GoodsPromotionUrlGenerateResponse func (c *Client) GoodsPromotionUrlGenerate(ctx context.Context, notMustParams ...Params) *GoodsPromotionUrlGenerateResult { // 参数 params := NewParamsWithType("pdd.ddk.goods.promotion.url.generate", notMustParams...) - params.Set("p_id", c.config.Pid) + params.Set("p_id", c.GetPid()) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.goods.recommend.get.go b/service/pinduoduo/pdd.ddk.goods.recommend.get.go index 938a9fb0..7ffa593e 100644 --- a/service/pinduoduo/pdd.ddk.goods.recommend.get.go +++ b/service/pinduoduo/pdd.ddk.goods.recommend.get.go @@ -83,7 +83,7 @@ func newGoodsRecommendGetResult(result GoodsRecommendGetResponse, body []byte, h func (c *Client) GoodsRecommendGet(ctx context.Context, notMustParams ...Params) *GoodsRecommendGetResult { // 参数 params := NewParamsWithType("pdd.ddk.goods.recommend.get", notMustParams...) - params.Set("pid", c.config.Pid) + params.Set("pid", c.GetPid()) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.goods.search.go b/service/pinduoduo/pdd.ddk.goods.search.go index 67d54a74..94968b59 100644 --- a/service/pinduoduo/pdd.ddk.goods.search.go +++ b/service/pinduoduo/pdd.ddk.goods.search.go @@ -97,7 +97,7 @@ func newGoodsSearchResult(result GoodsSearchResponse, body []byte, http goreques func (c *Client) GoodsSearch(ctx context.Context, notMustParams ...Params) *GoodsSearchResult { // 参数 params := NewParamsWithType("pdd.ddk.goods.search", notMustParams...) - params.Set("pid", c.config.Pid) + params.Set("pid", c.GetPid()) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.member.authority.query.go b/service/pinduoduo/pdd.ddk.member.authority.query.go index 805f2d62..2fb146e6 100644 --- a/service/pinduoduo/pdd.ddk.member.authority.query.go +++ b/service/pinduoduo/pdd.ddk.member.authority.query.go @@ -29,7 +29,7 @@ func newMemberAuthorityQueryResult(result MemberAuthorityQueryResponse, body []b func (c *Client) MemberAuthorityQuery(ctx context.Context, notMustParams ...Params) *MemberAuthorityQueryResult { // 参数 params := NewParamsWithType("pdd.ddk.member.authority.query", notMustParams...) - params.Set("pid", c.config.Pid) + params.Set("pid", c.GetPid()) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.resource.url.gen.go b/service/pinduoduo/pdd.ddk.resource.url.gen.go index 224a1c89..149a29e7 100644 --- a/service/pinduoduo/pdd.ddk.resource.url.gen.go +++ b/service/pinduoduo/pdd.ddk.resource.url.gen.go @@ -55,7 +55,7 @@ func newResourceUrlGenResult(result ResourceUrlGenResponse, body []byte, http go func (c *Client) ResourceUrlGen(ctx context.Context, notMustParams ...Params) *ResourceUrlGenResult { // 参数 params := NewParamsWithType("pdd.ddk.resource.url.gen", notMustParams...) - params.Set("pid", c.config.Pid) + params.Set("pid", c.GetPid()) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.rp.prom.url.generate.go b/service/pinduoduo/pdd.ddk.rp.prom.url.generate.go index 0d7a099d..35a48a9f 100644 --- a/service/pinduoduo/pdd.ddk.rp.prom.url.generate.go +++ b/service/pinduoduo/pdd.ddk.rp.prom.url.generate.go @@ -70,7 +70,7 @@ func newRpPromUrlGenerateResult(result RpPromUrlGenerateResponse, body []byte, h func (c *Client) RpPromUrlGenerate(ctx context.Context, notMustParams ...Params) *RpPromUrlGenerateResult { // 参数 params := NewParamsWithType("pdd.ddk.rp.prom.url.generate", notMustParams...) - params.Set("p_id_list", []string{c.config.Pid}) + params.Set("p_id_list", []string{c.GetPid()}) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/pdd.ddk.top.goods.list.query.go b/service/pinduoduo/pdd.ddk.top.goods.list.query.go index e43d83a2..ce13ec1b 100644 --- a/service/pinduoduo/pdd.ddk.top.goods.list.query.go +++ b/service/pinduoduo/pdd.ddk.top.goods.list.query.go @@ -63,7 +63,7 @@ func newTopGoodsListQueryResult(result TopGoodsListQueryResponse, body []byte, h func (c *Client) TopGoodsListQuery(ctx context.Context, notMustParams ...Params) *TopGoodsListQueryResult { // 参数 params := NewParamsWithType("pdd.ddk.top.goods.list.query", notMustParams...) - params.Set("p_id", c.config.Pid) + params.Set("p_id", c.GetPid()) // 请求 request, err := c.request(ctx, params) // 定义 diff --git a/service/pinduoduo/request.go b/service/pinduoduo/request.go index b388d256..eb41a069 100644 --- a/service/pinduoduo/request.go +++ b/service/pinduoduo/request.go @@ -2,9 +2,9 @@ package pinduoduo import ( "context" + "fmt" "github.com/dtapps/go-library" "github.com/dtapps/go-library/utils/gorequest" - "github.com/dtapps/go-library/utils/gostring" ) func (c *Client) request(ctx context.Context, params map[string]interface{}) (gorequest.Response, error) { @@ -13,7 +13,7 @@ func (c *Client) request(ctx context.Context, params map[string]interface{}) (go c.Sign(params) // 创建请求 - client := c.client + client := c.requestClient // 设置参数 client.SetParams(params) @@ -25,11 +25,8 @@ func (c *Client) request(ctx context.Context, params map[string]interface{}) (go } // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddlewareCustom(ctx, gostring.ToString(params["type"]), request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddlewareCustom(ctx, gostring.ToString(params["type"]), request, go_library.Version()) + if c.log.status { + go c.log.client.MiddlewareCustom(ctx, fmt.Sprintf("%s", params["type"]), request, go_library.Version()) } return request, err diff --git a/service/pintoto/client.go b/service/pintoto/client.go index e9f9e4e9..36ceb8b5 100644 --- a/service/pintoto/client.go +++ b/service/pintoto/client.go @@ -1,55 +1,40 @@ package pintoto import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" "math" "strconv" ) -type ConfigClient struct { - AppKey string - AppSecret string - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + AppKey string + AppSecret string } -// Client 电影票服务 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appKey string + appSecret string + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appKey = config.AppKey + c.config.appSecret = config.AppSecret - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/pintoto/config.go b/service/pintoto/config.go new file mode 100644 index 00000000..88a8bd15 --- /dev/null +++ b/service/pintoto/config.go @@ -0,0 +1,12 @@ +package pintoto + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/pintoto/const.go b/service/pintoto/const.go index 2ba05455..bac5201a 100644 --- a/service/pintoto/const.go +++ b/service/pintoto/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "pintoto" + LogTable = "pintoto" ) diff --git a/service/pintoto/get.go b/service/pintoto/get.go index d5fba3a8..03777cd4 100644 --- a/service/pintoto/get.go +++ b/service/pintoto/get.go @@ -1,8 +1,15 @@ package pintoto +import "github.com/dtapps/go-library/utils/golog" + func (c *Client) GetAppKey() string { - return c.config.AppKey + return c.config.appKey } + func (c *Client) GetAppSecret() string { - return c.config.AppSecret + return c.config.appSecret +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/pintoto/movie_info_get_hot_list.go b/service/pintoto/movie_info_get_hot_list.go index 6b26418e..fa1932db 100644 --- a/service/pintoto/movie_info_get_hot_list.go +++ b/service/pintoto/movie_info_get_hot_list.go @@ -20,7 +20,7 @@ type GetHotListResponse struct { Pic string `json:"pic"` // 海报URL地址 FilmTypes string `json:"filmTypes"` // 影片类型 LikeNum int `json:"likeNum"` // 想看人数 - Duration int `json:"duration"` // 时长,分钟 + Duration int64 `json:"duration"` // 时长,分钟 Cast string `json:"cast"` // 主演 FilmId int `json:"filmId"` // 影片id Grade string `json:"grade"` // 评分 diff --git a/service/pintoto/movie_info_get_schedule_list.go b/service/pintoto/movie_info_get_schedule_list.go index 9b7bf41a..eef70c2a 100644 --- a/service/pintoto/movie_info_get_schedule_list.go +++ b/service/pintoto/movie_info_get_schedule_list.go @@ -16,7 +16,7 @@ type GetScheduleListResponse struct { NetPrice int `json:"netPrice"` // 参考价,单位:分 Language string `json:"language"` // 语言 ShowDate string `json:"showDate"` // - Duration int `json:"duration"` // 时长,分钟 + Duration int64 `json:"duration"` // 时长,分钟 ShowId string `json:"showId"` // 场次标识 StopSellTime string `json:"stopSellTime"` // 停售时间 CinemaId int `json:"cinemaId"` // 影院id diff --git a/service/pintoto/movie_info_get_soon_list.go b/service/pintoto/movie_info_get_soon_list.go index eaaf15d7..75cc10fa 100644 --- a/service/pintoto/movie_info_get_soon_list.go +++ b/service/pintoto/movie_info_get_soon_list.go @@ -20,7 +20,7 @@ type GetSoonListResponse struct { Pic string `json:"pic"` // 海报URL地址 FilmTypes string `json:"filmTypes"` // 影片类型 LikeNum int `json:"likeNum"` // 想看人数 - Duration int `json:"duration"` // 时长,分钟 + Duration int64 `json:"duration"` // 时长,分钟 Cast string `json:"cast"` // 主演 FilmId int `json:"filmId"` // 影片id Grade interface{} `json:"grade"` // 评分 diff --git a/service/pintoto/request.go b/service/pintoto/request.go index bf16a8bc..c1d43204 100644 --- a/service/pintoto/request.go +++ b/service/pintoto/request.go @@ -18,7 +18,7 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte params["sign"] = c.getSign(c.GetAppSecret(), params) // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -35,12 +35,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/taobao/client.go b/service/taobao/client.go index 0dd79735..d1cce318 100644 --- a/service/taobao/client.go +++ b/service/taobao/client.go @@ -1,58 +1,42 @@ package taobao import ( - "fmt" - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "github.com/dtapps/go-library/utils/gostring" - "gorm.io/gorm" - "regexp" - "strconv" ) -type ConfigClient struct { - AppKey string // 应用Key - AppSecret string // 密钥 - AdzoneId int64 // mm_xxx_xxx_xxx的第三位 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + AppKey string // 应用Key + AppSecret string // 密钥 + AdzoneId int64 // mm_xxx_xxx_xxx的第三位 } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appKey string // 应用Key + appSecret string // 密钥 + adzoneId int64 // mm_xxx_xxx_xxx的第三位 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() - c.client.Uri = apiUrl + c.config.appKey = config.AppKey + c.config.appSecret = config.AppSecret + c.config.adzoneId = config.AdzoneId - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() + c.requestClient.Uri = apiUrl return c, nil } @@ -66,41 +50,3 @@ type ErrResp struct { RequestId string `json:"request_id"` } `json:"error_response"` } - -func (c *Client) ZkFinalPriceParseInt64(ZkFinalPrice string) int64 { - parseInt, err := strconv.ParseInt(ZkFinalPrice, 10, 64) - if err != nil { - re := regexp.MustCompile("[0-9]+") - SalesTipMap := re.FindAllString(ZkFinalPrice, -1) - if len(SalesTipMap) == 2 { - return gostring.ToInt64(fmt.Sprintf("%s%s", SalesTipMap[0], SalesTipMap[1])) * 10 - } else { - return gostring.ToInt64(SalesTipMap[0]) * 100 - } - } else { - return parseInt * 100 - } -} - -func (c *Client) CommissionRateParseInt64(CommissionRate string) int64 { - parseInt, err := strconv.ParseInt(CommissionRate, 10, 64) - if err != nil { - re := regexp.MustCompile("[0-9]+") - SalesTipMap := re.FindAllString(CommissionRate, -1) - if len(SalesTipMap) == 2 { - return gostring.ToInt64(fmt.Sprintf("%s%s", SalesTipMap[0], SalesTipMap[1])) - } else { - return gostring.ToInt64(SalesTipMap[0]) - } - } else { - return parseInt - } -} - -func (c *Client) CouponAmountToInt64(CouponAmount int64) int64 { - return CouponAmount * 100 -} - -func (c *Client) CommissionIntegralToInt64(GoodsPrice, CouponProportion int64) int64 { - return (GoodsPrice * CouponProportion) / 100 -} diff --git a/service/taobao/config.go b/service/taobao/config.go new file mode 100644 index 00000000..31bf6a63 --- /dev/null +++ b/service/taobao/config.go @@ -0,0 +1,12 @@ +package taobao + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/taobao/const.go b/service/taobao/const.go index 712f434c..54606ef9 100644 --- a/service/taobao/const.go +++ b/service/taobao/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "taobao" + LogTable = "taobao" ) diff --git a/service/taobao/get.go b/service/taobao/get.go index 35131bb1..9a218fcc 100644 --- a/service/taobao/get.go +++ b/service/taobao/get.go @@ -1,13 +1,19 @@ package taobao +import "github.com/dtapps/go-library/utils/golog" + func (c *Client) GetAppKey() string { - return c.config.AppKey + return c.config.appKey } func (c *Client) GetAppSecret() string { - return c.config.AppSecret + return c.config.appSecret } func (c *Client) GetAdzoneId() int64 { - return c.config.AdzoneId + return c.config.adzoneId +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/taobao/help.md b/service/taobao/help.md deleted file mode 100644 index 0294f86c..00000000 --- a/service/taobao/help.md +++ /dev/null @@ -1,2 +0,0 @@ -https://market.m.taobao.com/app/qn/toutiao-new/index-pc.html#/detail/10628679 -https://www.yuque.com/docs/share/20abfe17-16ef-41f9-9182-412474cce0bd \ No newline at end of file diff --git a/service/taobao/params.go b/service/taobao/params.go index 7d3a7a1f..26445b11 100644 --- a/service/taobao/params.go +++ b/service/taobao/params.go @@ -25,7 +25,7 @@ func NewParamsWithType(_method string, params ...Params) Params { p["format"] = "json" p["v"] = "2.0" p["sign_method"] = "md5" - p["partner_id"] = "Nilorg" + //p["partner_id"] = "Nilorg" for _, v := range params { p.SetParams(v) } diff --git a/service/taobao/request.go b/service/taobao/request.go index 1e18150d..cb1cd5e5 100644 --- a/service/taobao/request.go +++ b/service/taobao/request.go @@ -2,9 +2,9 @@ package taobao import ( "context" + "fmt" "github.com/dtapps/go-library" "github.com/dtapps/go-library/utils/gorequest" - "github.com/dtapps/go-library/utils/gostring" ) func (c *Client) request(ctx context.Context, params map[string]interface{}) (gorequest.Response, error) { @@ -13,7 +13,7 @@ func (c *Client) request(ctx context.Context, params map[string]interface{}) (go c.Sign(params) // 创建请求 - client := c.client + client := c.requestClient // 设置参数 client.SetParams(params) @@ -24,12 +24,9 @@ func (c *Client) request(ctx context.Context, params map[string]interface{}) (go return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddlewareCustom(ctx, gostring.ToString(params["method"]), request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddlewareCustom(ctx, gostring.ToString(params["method"]), request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.MiddlewareCustom(ctx, fmt.Sprintf("%s", params["method"]), request, go_library.Version()) } return request, err diff --git a/service/taobao/tbk.dg.material.optional.go b/service/taobao/tbk.dg.material.optional.go index cb357151..c0d32f38 100644 --- a/service/taobao/tbk.dg.material.optional.go +++ b/service/taobao/tbk.dg.material.optional.go @@ -23,7 +23,7 @@ type TbkDgMaterialOptionalResponse struct { IncludeMkt string `json:"include_mkt"` InfoDxjh string `json:"info_dxjh"` ItemDescription string `json:"item_description"` - ItemId int64 `json:"item_id"` + ItemId string `json:"item_id"` ItemUrl string `json:"item_url"` LevelOneCategoryId int64 `json:"level_one_category_id"` LevelOneCategoryName string `json:"level_one_category_name"` @@ -60,8 +60,9 @@ type TbkDgMaterialOptionalResponse struct { CouponAmount string `json:"coupon_amount"` } `json:"map_data"` } `json:"result_list"` - TotalResults int64 `json:"total_results"` - RequestId string `json:"request_id"` + TotalResults int64 `json:"total_results"` + RequestId string `json:"request_id"` + PageResultKey string `json:"page_result_key,omitempty"` } `json:"tbk_dg_material_optional_response"` } diff --git a/service/taobao/tbk.dg.optimus.material.go b/service/taobao/tbk.dg.optimus.material.go index 3d72fe6a..d0f7b3ad 100644 --- a/service/taobao/tbk.dg.optimus.material.go +++ b/service/taobao/tbk.dg.optimus.material.go @@ -24,7 +24,7 @@ type TbkDgOptimusMaterialResponse struct { CouponTotalCount int `json:"coupon_total_count"` CpaRewardType string `json:"cpa_reward_type"` ItemDescription string `json:"item_description"` - ItemId int64 `json:"item_id"` + ItemId string `json:"item_id"` JhsPriceUspList string `json:"jhs_price_usp_list"` LevelOneCategoryId int64 `json:"level_one_category_id"` LevelOneCategoryName string `json:"level_one_category_name"` @@ -45,7 +45,8 @@ type TbkDgOptimusMaterialResponse struct { ZkFinalPrice string `json:"zk_final_price"` } `json:"map_data"` } `json:"result_list"` - RequestId string `json:"request_id"` + RequestId string `json:"request_id"` + TotalCount int64 `json:"total_count,omitempty"` } `json:"tbk_dg_optimus_material_response"` } @@ -61,7 +62,7 @@ func newTbkDgOptimusMaterialResult(result TbkDgOptimusMaterialResponse, body []b } // TbkDgOptimusMaterial 淘宝客-推广者-物料精选 -// https://open.taobao.com/api.htm?spm=a219a.7386797.0.0.5d67669aIeQeVI&source=search&docId=33947&docType=2 +// https://open.taobao.com/api.htm?docId=33947&docType=2&source=search func (c *Client) TbkDgOptimusMaterial(ctx context.Context, notMustParams ...Params) *TbkDgOptimusMaterialResult { // 参数 params := NewParamsWithType("taobao.tbk.dg.optimus.material", notMustParams...) diff --git a/service/wechatminiprogram/cgi-bin.token.go b/service/wechatminiprogram/cgi-bin.token.go index 2d6f4eb5..cc535a8a 100644 --- a/service/wechatminiprogram/cgi-bin.token.go +++ b/service/wechatminiprogram/cgi-bin.token.go @@ -31,7 +31,7 @@ func newCgiBinTokenResult(result CgiBinTokenResponse, body []byte, http goreques // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html func (c *Client) CgiBinToken(ctx context.Context) *CgiBinTokenResult { // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", c.getAppId(), c.getAppSecret()), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", c.GetAppId(), c.GetAppSecret()), map[string]interface{}{}, http.MethodGet) // 定义 var response CgiBinTokenResponse err = json.Unmarshal(request.ResponseBody, &response) diff --git a/service/wechatminiprogram/cgi-bin.token.monitor.go b/service/wechatminiprogram/cgi-bin.token.monitor.go index 6edf54c4..5cd35836 100644 --- a/service/wechatminiprogram/cgi-bin.token.monitor.go +++ b/service/wechatminiprogram/cgi-bin.token.monitor.go @@ -7,14 +7,14 @@ import ( ) func (c *Client) GetAccessTokenMonitor(ctx context.Context) (string, error) { - if c.config.RedisClient.Db == nil { + if c.cache.redisClient.Db == nil { return "", errors.New("驱动没有初始化") } result := c.GetCallBackIp(ctx) if len(result.Result.IpList) <= 0 { token := c.CgiBinToken(ctx) - c.config.RedisClient.Set(ctx, c.getAccessTokenCacheKeyName(), token.Result.AccessToken, time.Second*7000) + c.cache.redisClient.Set(ctx, c.getAccessTokenCacheKeyName(), token.Result.AccessToken, time.Second*7000) return token.Result.AccessToken, nil } - return c.config.AccessToken, nil + return c.config.accessToken, nil } diff --git a/service/wechatminiprogram/cgi-bin.token.rdb.go b/service/wechatminiprogram/cgi-bin.token.rdb.go index f876f78a..11a20ad2 100644 --- a/service/wechatminiprogram/cgi-bin.token.rdb.go +++ b/service/wechatminiprogram/cgi-bin.token.rdb.go @@ -2,22 +2,21 @@ package wechatminiprogram import ( "context" - "fmt" "time" ) func (c *Client) GetAccessToken(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.AccessToken + if c.cache.redisClient.Db == nil { + return c.config.accessToken } - newCache := c.config.RedisClient.NewSimpleStringCache(c.config.RedisClient.NewStringOperation(), time.Second*7000) + newCache := c.cache.redisClient.NewSimpleStringCache(c.cache.redisClient.NewStringOperation(), time.Second*7000) newCache.DBGetter = func() string { token := c.CgiBinToken(ctx) return token.Result.AccessToken } - return newCache.GetCache(c.getAccessTokenCacheKeyName()) + return newCache.GetCache(ctx, c.getAccessTokenCacheKeyName()) } func (c *Client) getAccessTokenCacheKeyName() string { - return fmt.Sprintf("wechat_access_token:%v", c.config.AppId) + return c.cache.wechatAccessTokenPrefix + c.GetAppId() } diff --git a/service/wechatminiprogram/client.go b/service/wechatminiprogram/client.go index c64158b8..f15de25a 100644 --- a/service/wechatminiprogram/client.go +++ b/service/wechatminiprogram/client.go @@ -4,62 +4,55 @@ import ( "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppId string // 小程序唯一凭证,即 appId - AppSecret string // 小程序唯一凭证密钥,即 appSecret - AccessToken string // 接口调用凭证 - JsapiTicket string // 签名凭证 - RedisClient *dorm.RedisClient // 缓存数据库 - TokenDb *gorm.DB // 令牌数据库 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// 缓存前缀 +// wechat_mini:wechat_access_token: +type redisCachePrefixFun func() (wechatAccessToken string) +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string // 小程序唯一凭证,即 appId + AppSecret string // 小程序唯一凭证密钥,即 appSecret + RedisClient *dorm.RedisClient // 缓存数据库 + RedisCachePrefixFun redisCachePrefixFun // 缓存前缀 } -// Client 微信小程序服务 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appId string // 小程序唯一凭证,即 appId + appSecret string // 小程序唯一凭证密钥,即 appSecret + accessToken string // 接口调用凭证 + jsapiTicket string // 签名凭证 + } + cache struct { + redisClient *dorm.RedisClient // 缓存数据库 + wechatAccessTokenPrefix string // AccessToken + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appId = config.AppId + c.config.appSecret = config.AppSecret - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } + c.requestClient = gorequest.NewHttp() + + c.cache.redisClient = config.RedisClient + + c.cache.wechatAccessTokenPrefix = config.RedisCachePrefixFun() + if c.cache.wechatAccessTokenPrefix == "" { + return nil, redisCachePrefixNoConfig } return c, nil } - -// ConfigApp 配置 -func (c *Client) ConfigApp(appId, appSecret string) *Client { - c.config.AppId = appId - c.config.AppSecret = appSecret - return c -} diff --git a/service/wechatminiprogram/config.go b/service/wechatminiprogram/config.go new file mode 100644 index 00000000..a2a81c93 --- /dev/null +++ b/service/wechatminiprogram/config.go @@ -0,0 +1,19 @@ +package wechatminiprogram + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApp 配置 +func (c *Client) ConfigApp(appId, appSecret string) *Client { + c.config.appId = appId + c.config.appSecret = appSecret + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatminiprogram/const.go b/service/wechatminiprogram/const.go index 045e267e..ace19157 100644 --- a/service/wechatminiprogram/const.go +++ b/service/wechatminiprogram/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "wechatminiprogram" + LogTable = "wechatminiprogram" ) diff --git a/service/wechatminiprogram/error.go b/service/wechatminiprogram/error.go new file mode 100644 index 00000000..42069301 --- /dev/null +++ b/service/wechatminiprogram/error.go @@ -0,0 +1,7 @@ +package wechatminiprogram + +import "errors" + +var ( + redisCachePrefixNoConfig = errors.New("请配置 RedisCachePrefix") +) diff --git a/service/wechatminiprogram/get.go b/service/wechatminiprogram/get.go index ace1466f..a6e364d1 100644 --- a/service/wechatminiprogram/get.go +++ b/service/wechatminiprogram/get.go @@ -1,20 +1,23 @@ package wechatminiprogram -import "context" +import ( + "context" + "github.com/dtapps/go-library/utils/golog" +) -func (c *Client) getAppId() string { - return c.config.AppId +func (c *Client) GetAppId() string { + return c.config.appId } -func (c *Client) getAppSecret() string { - return c.config.AppSecret +func (c *Client) GetAppSecret() string { + return c.config.appSecret } func (c *Client) getAccessToken(ctx context.Context) string { - c.config.AccessToken = c.GetAccessToken(ctx) - return c.config.AccessToken + c.config.accessToken = c.GetAccessToken(ctx) + return c.config.accessToken } -func (c *Client) GetAppId() string { - return c.config.AppId +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/wechatminiprogram/request.go b/service/wechatminiprogram/request.go index b4c36c6f..530bb5a9 100644 --- a/service/wechatminiprogram/request.go +++ b/service/wechatminiprogram/request.go @@ -10,7 +10,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -30,12 +30,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/wechatminiprogram/sns.jscode2session.go b/service/wechatminiprogram/sns.jscode2session.go index 4fa9172a..ba8a4eaa 100644 --- a/service/wechatminiprogram/sns.jscode2session.go +++ b/service/wechatminiprogram/sns.jscode2session.go @@ -31,7 +31,7 @@ func newSnsJsCode2sessionResult(result SnsJsCode2sessionResponse, body []byte, h // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html func (c *Client) SnsJsCode2session(ctx context.Context, jsCode string) *SnsJsCode2sessionResult { // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", c.getAppId(), c.getAppSecret(), jsCode), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", c.GetAppId(), c.GetAppSecret(), jsCode), map[string]interface{}{}, http.MethodGet) // 定义 var response SnsJsCode2sessionResponse err = json.Unmarshal(request.ResponseBody, &response) diff --git a/service/wechatminiprogram/user_info.go b/service/wechatminiprogram/user_info.go index 37849eed..283ec18d 100644 --- a/service/wechatminiprogram/user_info.go +++ b/service/wechatminiprogram/user_info.go @@ -69,7 +69,7 @@ func (c *Client) UserInfo(ctx context.Context, param UserInfo) *UserInfoResult { if err != nil { return newUserInfoResult(response, err) } - if response.Watermark.AppID != c.getAppId() { + if response.Watermark.AppID != c.GetAppId() { return newUserInfoResult(response, errors.New("c id not match")) } return newUserInfoResult(response, err) diff --git a/service/wechatminiprogram/user_phone.go b/service/wechatminiprogram/user_phone.go index 6d3b9a37..23f79d1e 100644 --- a/service/wechatminiprogram/user_phone.go +++ b/service/wechatminiprogram/user_phone.go @@ -63,7 +63,7 @@ func (c *Client) UserPhone(ctx context.Context, param UserPhone) *UserPhoneResul if err != nil { return newUserPhoneResult(response, err) } - if response.Watermark.AppID != c.getAppId() { + if response.Watermark.AppID != c.GetAppId() { return newUserPhoneResult(response, errors.New("c id not match")) } return newUserPhoneResult(response, err) diff --git a/service/wechatoffice/cgi-bin.ticket.getticket.monitor.go b/service/wechatoffice/cgi-bin.ticket.getticket.monitor.go index 07657793..5f7cb3c0 100644 --- a/service/wechatoffice/cgi-bin.ticket.getticket.monitor.go +++ b/service/wechatoffice/cgi-bin.ticket.getticket.monitor.go @@ -8,15 +8,15 @@ import ( // GetJsapiTicketMonitor 监控api_ticket func (c *Client) GetJsapiTicketMonitor(ctx context.Context) (string, error) { - if c.config.RedisClient.Db == nil { + if c.cache.redisClient.Db == nil { return "", errors.New("驱动没有初始化") } result := c.DebugCgiBinTicketCheck(ctx) if result.Result.Errcode == 0 { - return c.config.JsapiTicket, nil + return c.config.jsapiTicket, nil } - c.config.AccessToken = c.GetAccessToken(ctx) + c.config.accessToken = c.GetAccessToken(ctx) token := c.CgiBinTicketGetTicket(ctx, "jsapi") - c.config.RedisClient.Db.Set(context.Background(), c.getJsapiTicketCacheKeyName(), token.Result.Ticket, time.Second*7000) + c.cache.redisClient.Set(ctx, c.getJsapiTicketCacheKeyName(), token.Result.Ticket, time.Second*7000) return token.Result.Ticket, nil } diff --git a/service/wechatoffice/cgi-bin.ticket.getticket.rdb.go b/service/wechatoffice/cgi-bin.ticket.getticket.rdb.go index d0a6a238..b5d0a7f7 100644 --- a/service/wechatoffice/cgi-bin.ticket.getticket.rdb.go +++ b/service/wechatoffice/cgi-bin.ticket.getticket.rdb.go @@ -2,23 +2,22 @@ package wechatoffice import ( "context" - "fmt" "time" ) // GetJsapiTicket 获取api_ticket func (c *Client) GetJsapiTicket(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.JsapiTicket + if c.cache.redisClient.Db == nil { + return c.config.jsapiTicket } - newCache := c.config.RedisClient.NewSimpleStringCache(c.config.RedisClient.NewStringOperation(), time.Second*7000) + newCache := c.cache.redisClient.NewSimpleStringCache(c.cache.redisClient.NewStringOperation(), time.Second*7000) newCache.DBGetter = func() string { token := c.CgiBinTicketGetTicket(ctx, "jsapi") return token.Result.Ticket } - return newCache.GetCache(c.getJsapiTicketCacheKeyName()) + return newCache.GetCache(ctx, c.getJsapiTicketCacheKeyName()) } func (c *Client) getJsapiTicketCacheKeyName() string { - return fmt.Sprintf("wechat_jsapi_ticket:%v", c.GetAppId()) + return c.cache.wechatJsapiTicketPrefix + c.GetAppId() } diff --git a/service/wechatoffice/cgi-bin.token.monitor.go b/service/wechatoffice/cgi-bin.token.monitor.go index a9203e23..44ad6ec7 100644 --- a/service/wechatoffice/cgi-bin.token.monitor.go +++ b/service/wechatoffice/cgi-bin.token.monitor.go @@ -7,14 +7,14 @@ import ( ) func (c *Client) GetAccessTokenMonitor(ctx context.Context) (string, error) { - if c.config.RedisClient.Db == nil { + if c.cache.redisClient.Db == nil { return "", errors.New("驱动没有初始化") } result := c.GetCallBackIp(ctx) if len(result.Result.IpList) > 0 { - return c.config.AccessToken, nil + return c.config.accessToken, nil } token := c.CgiBinToken(ctx) - c.config.RedisClient.Db.Set(context.Background(), c.getAccessTokenCacheKeyName(), token.Result.AccessToken, time.Second*7000) + c.cache.redisClient.Set(ctx, c.getAccessTokenCacheKeyName(), token.Result.AccessToken, time.Second*7000) return token.Result.AccessToken, nil } diff --git a/service/wechatoffice/cgi-bin.token.rdb.go b/service/wechatoffice/cgi-bin.token.rdb.go index 784a30d6..da22002b 100644 --- a/service/wechatoffice/cgi-bin.token.rdb.go +++ b/service/wechatoffice/cgi-bin.token.rdb.go @@ -2,22 +2,21 @@ package wechatoffice import ( "context" - "fmt" "time" ) func (c *Client) GetAccessToken(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.AccessToken + if c.cache.redisClient.Db == nil { + return c.config.accessToken } - newCache := c.config.RedisClient.NewSimpleStringCache(c.config.RedisClient.NewStringOperation(), time.Second*7000) + newCache := c.cache.redisClient.NewSimpleStringCache(c.cache.redisClient.NewStringOperation(), time.Second*7000) newCache.DBGetter = func() string { token := c.CgiBinToken(ctx) return token.Result.AccessToken } - return newCache.GetCache(c.getAccessTokenCacheKeyName()) + return newCache.GetCache(ctx, c.getAccessTokenCacheKeyName()) } func (c *Client) getAccessTokenCacheKeyName() string { - return fmt.Sprintf("wechat_access_token:%v", c.GetAppId()) + return c.cache.wechatAccessTokenPrefix + c.GetAppId() } diff --git a/service/wechatoffice/client.go b/service/wechatoffice/client.go index b2f70908..db3a3aee 100644 --- a/service/wechatoffice/client.go +++ b/service/wechatoffice/client.go @@ -4,61 +4,57 @@ import ( "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppId string // 小程序唯一凭证,即 appId - AppSecret string // 小程序唯一凭证密钥,即 appSecret - AccessToken string // 接口调用凭证 - JsapiTicket string // 签名凭证 - RedisClient *dorm.RedisClient // 缓存数据库 - TokenDb *gorm.DB // 令牌数据库 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// 缓存前缀 +// wechat_office:wechat_access_token: +// wechat_office:wechat_jsapi_ticket: +type redisCachePrefixFun func() (wechatAccessToken, wechatJsapiTicket string) + +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string // 小程序唯一凭证,即 appId + AppSecret string // 小程序唯一凭证密钥,即 appSecret + RedisClient *dorm.RedisClient // 缓存数据库 + RedisCachePrefixFun redisCachePrefixFun // 缓存前缀 } -// Client 微信公众号服务 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appId string // 小程序唯一凭证,即 appId + appSecret string // 小程序唯一凭证密钥,即 appSecret + accessToken string // 接口调用凭证 + jsapiTicket string // 签名凭证 + } + cache struct { + redisClient *dorm.RedisClient // 缓存数据库 + wechatAccessTokenPrefix string // AccessToken + wechatJsapiTicketPrefix string // JsapiTicket + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appId = config.AppId + c.config.appSecret = config.AppSecret - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } + c.requestClient = gorequest.NewHttp() + + c.cache.redisClient = config.RedisClient + + c.cache.wechatAccessTokenPrefix, c.cache.wechatJsapiTicketPrefix = config.RedisCachePrefixFun() + if c.cache.wechatAccessTokenPrefix == "" || c.cache.wechatJsapiTicketPrefix == "" { + return nil, redisCachePrefixNoConfig } return c, nil } - -// ConfigApp 配置 -func (c *Client) ConfigApp(appId, appSecret string) *Client { - c.config.AppId = appId - c.config.AppSecret = appSecret - return c -} diff --git a/service/wechatoffice/config.go b/service/wechatoffice/config.go new file mode 100644 index 00000000..a9f5149a --- /dev/null +++ b/service/wechatoffice/config.go @@ -0,0 +1,19 @@ +package wechatoffice + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApp 配置 +func (c *Client) ConfigApp(appId, appSecret string) *Client { + c.config.appId = appId + c.config.appSecret = appSecret + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatoffice/const.go b/service/wechatoffice/const.go index 445164cb..30f482cb 100644 --- a/service/wechatoffice/const.go +++ b/service/wechatoffice/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "wechatoffice" + LogTable = "wechatoffice" ) diff --git a/service/wechatoffice/error.go b/service/wechatoffice/error.go new file mode 100644 index 00000000..7de12c2f --- /dev/null +++ b/service/wechatoffice/error.go @@ -0,0 +1,7 @@ +package wechatoffice + +import "errors" + +var ( + redisCachePrefixNoConfig = errors.New("请配置 RedisCachePrefix") +) diff --git a/service/wechatoffice/get.go b/service/wechatoffice/get.go index cfcfd1db..5e6907c4 100644 --- a/service/wechatoffice/get.go +++ b/service/wechatoffice/get.go @@ -1,21 +1,28 @@ package wechatoffice -import "context" +import ( + "context" + "github.com/dtapps/go-library/utils/golog" +) func (c *Client) GetAppId() string { - return c.config.AppId + return c.config.appId } func (c *Client) GetAppSecret() string { - return c.config.AppSecret + return c.config.appSecret } func (c *Client) getAccessToken(ctx context.Context) string { - c.config.AccessToken = c.GetAccessToken(ctx) - return c.config.AccessToken + c.config.accessToken = c.GetAccessToken(ctx) + return c.config.accessToken } func (c *Client) getJsapiTicket(ctx context.Context) string { - c.config.JsapiTicket = c.GetJsapiTicket(ctx) - return c.config.JsapiTicket + c.config.jsapiTicket = c.GetJsapiTicket(ctx) + return c.config.jsapiTicket +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/wechatoffice/request.go b/service/wechatoffice/request.go index 7a0729cc..275ed7b0 100644 --- a/service/wechatoffice/request.go +++ b/service/wechatoffice/request.go @@ -10,7 +10,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -30,12 +30,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/wechatoffice/share.go b/service/wechatoffice/share.go index 4a7fbb97..6e03a83d 100644 --- a/service/wechatoffice/share.go +++ b/service/wechatoffice/share.go @@ -29,13 +29,13 @@ func newShareResult(result ShareResponse, err error) *ShareResult { func (c *Client) Share(ctx context.Context, url string) *ShareResult { c.getAccessToken(ctx) - c.config.JsapiTicket = c.GetJsapiTicket(ctx) + c.config.jsapiTicket = c.GetJsapiTicket(ctx) var response ShareResponse response.AppId = c.GetAppId() response.NonceStr = gorandom.Alphanumeric(32) response.Timestamp = time.Now().Unix() response.Url = url - response.RawString = fmt.Sprintf("jsapi_ticket=%v&noncestr=%v×tamp=%v&url=%v", c.config.JsapiTicket, response.NonceStr, response.Timestamp, response.Url) + response.RawString = fmt.Sprintf("jsapi_ticket=%v&noncestr=%v×tamp=%v&url=%v", c.config.jsapiTicket, response.NonceStr, response.Timestamp, response.Url) t := sha1.New() _, err := io.WriteString(t, response.RawString) response.Signature = fmt.Sprintf("%x", t.Sum(nil)) diff --git a/service/wechatopen/cgi-bin.account.getaccountbasicinfo.go b/service/wechatopen/cgi-bin.account.getaccountbasicinfo.go index 123a4df3..fda4f703 100644 --- a/service/wechatopen/cgi-bin.account.getaccountbasicinfo.go +++ b/service/wechatopen/cgi-bin.account.getaccountbasicinfo.go @@ -47,20 +47,36 @@ type CgiBinAccountGetAccountBasicInfoResult struct { Result CgiBinAccountGetAccountBasicInfoResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinAccountGetAccountBasicInfoResult(result CgiBinAccountGetAccountBasicInfoResponse, body []byte, http gorequest.Response, err error) *CgiBinAccountGetAccountBasicInfoResult { - return &CgiBinAccountGetAccountBasicInfoResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinAccountGetAccountBasicInfoResult(result CgiBinAccountGetAccountBasicInfoResponse, body []byte, http gorequest.Response) *CgiBinAccountGetAccountBasicInfoResult { + return &CgiBinAccountGetAccountBasicInfoResult{Result: result, Body: body, Http: http} } // CgiBinAccountGetAccountBasicInfo 获取基本信息 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Mini_Program_Basic_Info/Mini_Program_Information_Settings.html -func (c *Client) CgiBinAccountGetAccountBasicInfo(ctx context.Context) *CgiBinAccountGetAccountBasicInfoResult { +func (c *Client) CgiBinAccountGetAccountBasicInfo(ctx context.Context) (*CgiBinAccountGetAccountBasicInfoResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/account/getaccountbasicinfo?access_token=%v", c.GetAuthorizerAccessToken(ctx)), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/account/getaccountbasicinfo?access_token=%v", c.GetAuthorizerAccessToken(ctx)), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response CgiBinAccountGetAccountBasicInfoResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinAccountGetAccountBasicInfoResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinAccountGetAccountBasicInfoResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.component.api_authorizer_token.go b/service/wechatopen/cgi-bin.component.api_authorizer_token.go index 640760c3..974d337d 100644 --- a/service/wechatopen/cgi-bin.component.api_authorizer_token.go +++ b/service/wechatopen/cgi-bin.component.api_authorizer_token.go @@ -18,27 +18,41 @@ type CgiBinComponentApiAuthorizerTokenResult struct { Result CgiBinComponentApiAuthorizerTokenResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 authorizerAppid string // 授权方 appid } -func newCgiBinComponentApiAuthorizerTokenResult(result CgiBinComponentApiAuthorizerTokenResponse, body []byte, http gorequest.Response, err error, authorizerAppid string) *CgiBinComponentApiAuthorizerTokenResult { - return &CgiBinComponentApiAuthorizerTokenResult{Result: result, Body: body, Http: http, Err: err, authorizerAppid: authorizerAppid} +func newCgiBinComponentApiAuthorizerTokenResult(result CgiBinComponentApiAuthorizerTokenResponse, body []byte, http gorequest.Response, authorizerAppid string) *CgiBinComponentApiAuthorizerTokenResult { + return &CgiBinComponentApiAuthorizerTokenResult{Result: result, Body: body, Http: http, authorizerAppid: authorizerAppid} } // CgiBinComponentApiAuthorizerToken 获取/刷新接口调用令牌 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/token/api_authorizer_token.html -func (c *Client) CgiBinComponentApiAuthorizerToken(ctx context.Context, authorizerRefreshToken string) *CgiBinComponentApiAuthorizerTokenResult { +func (c *Client) CgiBinComponentApiAuthorizerToken(ctx context.Context, authorizerRefreshToken string) (*CgiBinComponentApiAuthorizerTokenResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 param := gorequest.NewParams() - param["component_appid"] = c.config.ComponentAppId // 第三方平台 appid - param["authorizer_appid"] = c.config.AuthorizerAppid // 授权方 appid + param["component_appid"] = c.GetComponentAppId() // 第三方平台 appid + param["authorizer_appid"] = c.GetAuthorizerAppid() // 授权方 appid param["authorizer_refresh_token"] = authorizerRefreshToken // 授权码, 会在授权成功时返回给第三方平台 params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/component/api_authorizer_token?component_access_token=%v", c.GetComponentAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentApiAuthorizerTokenResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentApiAuthorizerTokenResult(response, request.ResponseBody, request, err, c.config.AuthorizerAppid) + if err != nil { + return nil, err + } + return newCgiBinComponentApiAuthorizerTokenResult(response, request.ResponseBody, request, param["authorizer_appid"].(string)), nil } diff --git a/service/wechatopen/cgi-bin.component.api_component_token.go b/service/wechatopen/cgi-bin.component.api_component_token.go index 32b65777..4c8f6bc4 100644 --- a/service/wechatopen/cgi-bin.component.api_component_token.go +++ b/service/wechatopen/cgi-bin.component.api_component_token.go @@ -16,26 +16,36 @@ type CgiBinComponentApiComponentTokenResult struct { Result CgiBinComponentApiComponentTokenResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinComponentApiComponentTokenResult(result CgiBinComponentApiComponentTokenResponse, body []byte, http gorequest.Response, err error) *CgiBinComponentApiComponentTokenResult { - return &CgiBinComponentApiComponentTokenResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinComponentApiComponentTokenResult(result CgiBinComponentApiComponentTokenResponse, body []byte, http gorequest.Response) *CgiBinComponentApiComponentTokenResult { + return &CgiBinComponentApiComponentTokenResult{Result: result, Body: body, Http: http} } // CgiBinComponentApiComponentToken 令牌 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/token/component_access_token.html -func (c *Client) CgiBinComponentApiComponentToken(ctx context.Context) *CgiBinComponentApiComponentTokenResult { +func (c *Client) CgiBinComponentApiComponentToken(ctx context.Context) (*CgiBinComponentApiComponentTokenResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 param := gorequest.NewParams() - param["component_appid"] = c.config.ComponentAppId // 第三方平台 appid - param["component_appsecret"] = c.config.ComponentAppSecret // 第三方平台 appsecret + param["component_appid"] = c.GetComponentAppId() // 第三方平台 appid + param["component_appsecret"] = c.GetComponentAppSecret() // 第三方平台 appsecret param["component_verify_ticket"] = c.GetComponentVerifyTicket(ctx) // 微信后台推送的 ticket params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, apiUrl+"/cgi-bin/component/api_component_token", params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentApiComponentTokenResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentApiComponentTokenResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinComponentApiComponentTokenResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.component.api_create_preauthcode.go b/service/wechatopen/cgi-bin.component.api_create_preauthcode.go index 4c5d7c55..33d35bd7 100644 --- a/service/wechatopen/cgi-bin.component.api_create_preauthcode.go +++ b/service/wechatopen/cgi-bin.component.api_create_preauthcode.go @@ -17,24 +17,35 @@ type CgiBinComponentApiCreatePreAuthCodenResult struct { Result CgiBinComponentApiCreatePreAuthCodenResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinComponentApiCreatePreAuthCodenResult(result CgiBinComponentApiCreatePreAuthCodenResponse, body []byte, http gorequest.Response, err error) *CgiBinComponentApiCreatePreAuthCodenResult { - return &CgiBinComponentApiCreatePreAuthCodenResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinComponentApiCreatePreAuthCodenResult(result CgiBinComponentApiCreatePreAuthCodenResponse, body []byte, http gorequest.Response) *CgiBinComponentApiCreatePreAuthCodenResult { + return &CgiBinComponentApiCreatePreAuthCodenResult{Result: result, Body: body, Http: http} } // CgiBinComponentApiCreatePreAuthCoden 预授权码 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/token/pre_auth_code.html -func (c *Client) CgiBinComponentApiCreatePreAuthCoden(ctx context.Context) *CgiBinComponentApiCreatePreAuthCodenResult { +func (c *Client) CgiBinComponentApiCreatePreAuthCoden(ctx context.Context) (*CgiBinComponentApiCreatePreAuthCodenResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 param := gorequest.NewParams() - param["component_appid"] = c.config.ComponentAppId // 第三方平台 appid + param["component_appid"] = c.GetComponentAppId() // 第三方平台 appid params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/component/api_create_preauthcode?component_access_token=%v", c.GetComponentAccessToken(ctx)), params, http.MethodPost) + + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentApiCreatePreAuthCodenResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentApiCreatePreAuthCodenResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinComponentApiCreatePreAuthCodenResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.component.api_get_authorizer_info.go b/service/wechatopen/cgi-bin.component.api_get_authorizer_info.go index 37fab16c..b1b581c0 100644 --- a/service/wechatopen/cgi-bin.component.api_get_authorizer_info.go +++ b/service/wechatopen/cgi-bin.component.api_get_authorizer_info.go @@ -75,25 +75,39 @@ type CgiBinComponentApiGetAuthorizerInfoResult struct { Result CgiBinComponentApiGetAuthorizerInfoResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinComponentApiGetAuthorizerInfoResult(result CgiBinComponentApiGetAuthorizerInfoResponse, body []byte, http gorequest.Response, err error) *CgiBinComponentApiGetAuthorizerInfoResult { - return &CgiBinComponentApiGetAuthorizerInfoResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinComponentApiGetAuthorizerInfoResult(result CgiBinComponentApiGetAuthorizerInfoResponse, body []byte, http gorequest.Response) *CgiBinComponentApiGetAuthorizerInfoResult { + return &CgiBinComponentApiGetAuthorizerInfoResult{Result: result, Body: body, Http: http} } // CgiBinComponentApiGetAuthorizerInfo 获取授权帐号详情 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/token/api_get_authorizer_info.html -func (c *Client) CgiBinComponentApiGetAuthorizerInfo(ctx context.Context) *CgiBinComponentApiGetAuthorizerInfoResult { +func (c *Client) CgiBinComponentApiGetAuthorizerInfo(ctx context.Context) (*CgiBinComponentApiGetAuthorizerInfoResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 param := gorequest.NewParams() - param["component_appid"] = c.config.ComponentAppId // 第三方平台 appid - param["authorizer_appid"] = c.config.AuthorizerAppid // 授权方 appid + param["component_appid"] = c.GetComponentAppId() // 第三方平台 appid + param["authorizer_appid"] = c.GetAuthorizerAppid() // 授权方 appid params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/component/api_get_authorizer_info?component_access_token=%v", c.GetComponentAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentApiGetAuthorizerInfoResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentApiGetAuthorizerInfoResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinComponentApiGetAuthorizerInfoResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.component.api_query_auth.go b/service/wechatopen/cgi-bin.component.api_query_auth.go index 5951d948..bbd0b7c1 100644 --- a/service/wechatopen/cgi-bin.component.api_query_auth.go +++ b/service/wechatopen/cgi-bin.component.api_query_auth.go @@ -31,25 +31,35 @@ type CgiBinComponentApiQueryAuthResult struct { Result CgiBinComponentApiQueryAuthResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinComponentApiQueryAuthResult(result CgiBinComponentApiQueryAuthResponse, body []byte, http gorequest.Response, err error) *CgiBinComponentApiQueryAuthResult { - return &CgiBinComponentApiQueryAuthResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinComponentApiQueryAuthResult(result CgiBinComponentApiQueryAuthResponse, body []byte, http gorequest.Response) *CgiBinComponentApiQueryAuthResult { + return &CgiBinComponentApiQueryAuthResult{Result: result, Body: body, Http: http} } // CgiBinComponentApiQueryAuth 使用授权码获取授权信息 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/token/authorization_info.html -func (c *Client) CgiBinComponentApiQueryAuth(ctx context.Context, authorizationCode string) *CgiBinComponentApiQueryAuthResult { +func (c *Client) CgiBinComponentApiQueryAuth(ctx context.Context, authorizationCode string) (*CgiBinComponentApiQueryAuthResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 param := gorequest.NewParams() - param["component_appid"] = c.config.ComponentAppId // 第三方平台 appid - param["authorization_code"] = authorizationCode // 授权码, 会在授权成功时返回给第三方平台 + param["component_appid"] = c.GetComponentAppId() // 第三方平台 appid + param["authorization_code"] = authorizationCode // 授权码, 会在授权成功时返回给第三方平台 params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/component/api_query_auth?component_access_token=%v", c.GetComponentAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentApiQueryAuthResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentApiQueryAuthResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinComponentApiQueryAuthResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.component.api_start_push_ticket.go b/service/wechatopen/cgi-bin.component.api_start_push_ticket.go index 90d45d8a..26e8d6b5 100644 --- a/service/wechatopen/cgi-bin.component.api_start_push_ticket.go +++ b/service/wechatopen/cgi-bin.component.api_start_push_ticket.go @@ -18,25 +18,35 @@ type CgiBinComponentApiStartPushTicketResult struct { Result CgiBinComponentApiStartPushTicketResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinComponentApiStartPushTicketResult(result CgiBinComponentApiStartPushTicketResponse, body []byte, http gorequest.Response, err error) *CgiBinComponentApiStartPushTicketResult { - return &CgiBinComponentApiStartPushTicketResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinComponentApiStartPushTicketResult(result CgiBinComponentApiStartPushTicketResponse, body []byte, http gorequest.Response) *CgiBinComponentApiStartPushTicketResult { + return &CgiBinComponentApiStartPushTicketResult{Result: result, Body: body, Http: http} } // CgiBinComponentApiStartPushTicket 启动ticket推送服务 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/token/component_verify_ticket_service.html -func (c *Client) CgiBinComponentApiStartPushTicket(ctx context.Context) *CgiBinComponentApiStartPushTicketResult { +func (c *Client) CgiBinComponentApiStartPushTicket(ctx context.Context) (*CgiBinComponentApiStartPushTicketResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 param := gorequest.NewParams() - param["component_appid"] = c.config.ComponentAppId // 平台型第三方平台的appid - param["component_secret"] = c.config.ComponentAppSecret // 平台型第三方平台的APPSECRET + param["component_appid"] = c.GetComponentAppId() // 平台型第三方平台的appid + param["component_secret"] = c.GetComponentAppSecret() // 平台型第三方平台的APPSECRET params := gorequest.NewParamsWith(param) // 请求 request, err := c.request(ctx, apiUrl+"/cgi-bin/component/api_start_push_ticket", params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentApiStartPushTicketResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentApiStartPushTicketResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinComponentApiStartPushTicketResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.component.fastregisterweapp.create.go b/service/wechatopen/cgi-bin.component.fastregisterweapp.create.go new file mode 100644 index 00000000..a899bdee --- /dev/null +++ b/service/wechatopen/cgi-bin.component.fastregisterweapp.create.go @@ -0,0 +1,120 @@ +package wechatopen + +import ( + "context" + "encoding/json" + "fmt" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type CgiBinComponentFastRegisterWeAppCreateResponse struct { + Errcode int `json:"errcode"` // 错误码 + Errmsg string `json:"errmsg"` // 错误信息 +} + +type CgiBinComponentFastRegisterWeAppCreateResult struct { + Result CgiBinComponentFastRegisterWeAppCreateResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 +} + +func newCgiBinComponentFastRegisterWeAppCreateResult(result CgiBinComponentFastRegisterWeAppCreateResponse, body []byte, http gorequest.Response) *CgiBinComponentFastRegisterWeAppCreateResult { + return &CgiBinComponentFastRegisterWeAppCreateResult{Result: result, Body: body, Http: http} +} + +// CgiBinComponentFastRegisterWeAppCreate 快速注册企业小程序 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/register-management/fast-registration-ent/registerMiniprogram.html +func (c *Client) CgiBinComponentFastRegisterWeAppCreate(ctx context.Context, notMustParams ...gorequest.Params) (*CgiBinComponentFastRegisterWeAppCreateResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + // 请求 + request, err := c.request(ctx, apiUrl+"/cgi-bin/component/fastregisterweapp?action=create&component_access_token="+c.GetComponentAccessToken(ctx), params, http.MethodPost) + if err != nil { + return nil, err + } + // 定义 + var response CgiBinComponentFastRegisterWeAppCreateResponse + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + return newCgiBinComponentFastRegisterWeAppCreateResult(response, request.ResponseBody, request), nil +} + +// ErrcodeInfo 错误描述 +func (resp *CgiBinComponentFastRegisterWeAppCreateResult) ErrcodeInfo() string { + switch resp.Result.Errcode { + case 89249: + return "该 appid 已有转正任务执行中,距上次任务 24h 后再试" + case 89247: + return "系统内部错误" + case 86004: + return "无效微信号" + case 61070: + return "法人姓名与微信号不一致" + case 89248: + return "企业代码类型无效,请选择正确类型填写" + case 89250: + return "未找到该任务" + case 89251: + return "模板消息已下发,待法人人脸核身校验" + case 89252: + return "法人&企业信息一致性校验中" + case 89253: + return "缺少参数" + case 89254: + return "第三方权限集不全,请补充权限集后重试" + case 89255: + return "code参数无效,请检查 code 长度以及内容是否正确;注意code_type的值不同需要传的 code 长度不一样" + } + return "系统繁忙" +} + +// StatusInfo 状态描述 +func (resp *CgiBinComponentFastRegisterWeAppCreateResult) StatusInfo(status int) string { + switch status { + case 100001: + return "已下发的模板消息法人并未确认且已超时(24h),未进行身份证校验" + case 100002: + return "已下发的模板消息法人并未确认且已超时(24h),未进行人脸识别校验" + case 100003: + return "已下发的模板消息法人并未确认且已超时(24h)" + case 101: + return "工商数据返回:“企业已注销”" + case 102: + return "工商数据返回:“企业不存在或企业信息未更新”" + case 103: + return "工商数据返回:“企业法定代表人姓名不一致”" + case 104: + return "工商数据返回:“企业法定代表人身份证号码不一致”" + case 105: + return "法定代表人身份证号码,工商数据未更新,请 5-15 个工作日之后尝试" + case 1000: + return "工商数据返回:“企业信息或法定代表人信息不一致”" + case 1001: + return "主体创建小程序数量达到上限" + case 1002: + return "主体违规命中黑名单" + case 1003: + return "管理员绑定账号数量达到上限" + case 1004: + return "管理员违规命中黑名单" + case 1005: + return "管理员手机绑定账号数量达到上限" + case 1006: + return "管理员手机号违规命中黑名单" + case 1007: + return "管理员身份证创建账号数量达到上限" + case 1008: + return "管理员身份证违规命中黑名单" + case -1: + return "企业与法人姓名不一致" + } + return fmt.Sprintf("%v", status) +} diff --git a/service/wechatopen/cgi-bin.component.fastregisterweapp.search.go b/service/wechatopen/cgi-bin.component.fastregisterweapp.search.go new file mode 100644 index 00000000..a2cc06e7 --- /dev/null +++ b/service/wechatopen/cgi-bin.component.fastregisterweapp.search.go @@ -0,0 +1,120 @@ +package wechatopen + +import ( + "context" + "encoding/json" + "fmt" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type CgiBinComponentFastRegisterWeAppSearchResponse struct { + Errcode int `json:"errcode"` // 错误码 + Errmsg string `json:"errmsg"` // 错误信息 +} + +type CgiBinComponentFastRegisterWeAppSearchResult struct { + Result CgiBinComponentFastRegisterWeAppSearchResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 +} + +func newCgiBinComponentFastRegisterWeAppSearchResult(result CgiBinComponentFastRegisterWeAppSearchResponse, body []byte, http gorequest.Response) *CgiBinComponentFastRegisterWeAppSearchResult { + return &CgiBinComponentFastRegisterWeAppSearchResult{Result: result, Body: body, Http: http} +} + +// CgiBinComponentFastRegisterWeAppSearch 快速注册企业小程序 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/register-management/fast-registration-ent/registerMiniprogram.html#%E4%BA%8C%E3%80%81%E6%9F%A5%E8%AF%A2%E5%88%9B%E5%BB%BA%E4%BB%BB%E5%8A%A1%E7%8A%B6%E6%80%81 +func (c *Client) CgiBinComponentFastRegisterWeAppSearch(ctx context.Context, notMustParams ...gorequest.Params) (*CgiBinComponentFastRegisterWeAppSearchResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + // 请求 + request, err := c.request(ctx, apiUrl+"/cgi-bin/component/fastregisterweapp?action=search&component_access_token="+c.GetComponentAccessToken(ctx), params, http.MethodPost) + if err != nil { + return nil, err + } + // 定义 + var response CgiBinComponentFastRegisterWeAppSearchResponse + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + return newCgiBinComponentFastRegisterWeAppSearchResult(response, request.ResponseBody, request), nil +} + +// ErrcodeInfo 错误描述 +func (resp *CgiBinComponentFastRegisterWeAppSearchResult) ErrcodeInfo() string { + switch resp.Result.Errcode { + case 89249: + return "该 appid 已有转正任务执行中,距上次任务 24h 后再试" + case 89247: + return "系统内部错误" + case 86004: + return "无效微信号" + case 61070: + return "法人姓名与微信号不一致" + case 89248: + return "企业代码类型无效,请选择正确类型填写" + case 89250: + return "未找到该任务" + case 89251: + return "模板消息已下发,待法人人脸核身校验" + case 89252: + return "法人&企业信息一致性校验中" + case 89253: + return "缺少参数" + case 89254: + return "第三方权限集不全,请补充权限集后重试" + case 89255: + return "code参数无效,请检查 code 长度以及内容是否正确;注意code_type的值不同需要传的 code 长度不一样" + } + return "系统繁忙" +} + +// StatusInfo 状态描述 +func (resp *CgiBinComponentFastRegisterWeAppSearchResult) StatusInfo(status int) string { + switch status { + case 100001: + return "已下发的模板消息法人并未确认且已超时(24h),未进行身份证校验" + case 100002: + return "已下发的模板消息法人并未确认且已超时(24h),未进行人脸识别校验" + case 100003: + return "已下发的模板消息法人并未确认且已超时(24h)" + case 101: + return "工商数据返回:“企业已注销”" + case 102: + return "工商数据返回:“企业不存在或企业信息未更新”" + case 103: + return "工商数据返回:“企业法定代表人姓名不一致”" + case 104: + return "工商数据返回:“企业法定代表人身份证号码不一致”" + case 105: + return "法定代表人身份证号码,工商数据未更新,请 5-15 个工作日之后尝试" + case 1000: + return "工商数据返回:“企业信息或法定代表人信息不一致”" + case 1001: + return "主体创建小程序数量达到上限" + case 1002: + return "主体违规命中黑名单" + case 1003: + return "管理员绑定账号数量达到上限" + case 1004: + return "管理员违规命中黑名单" + case 1005: + return "管理员手机绑定账号数量达到上限" + case 1006: + return "管理员手机号违规命中黑名单" + case 1007: + return "管理员身份证创建账号数量达到上限" + case 1008: + return "管理员身份证违规命中黑名单" + case -1: + return "企业与法人姓名不一致" + } + return fmt.Sprintf("%v", status) +} diff --git a/service/wechatopen/cgi-bin.component.getprivacysetting.go b/service/wechatopen/cgi-bin.component.getprivacysetting.go index ebe42023..47679145 100644 --- a/service/wechatopen/cgi-bin.component.getprivacysetting.go +++ b/service/wechatopen/cgi-bin.component.getprivacysetting.go @@ -49,24 +49,38 @@ type CgiBinComponentGetPrivacySettingResult struct { Result CgiBinComponentGetPrivacySettingResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinComponentGetPrivacySettingResult(result CgiBinComponentGetPrivacySettingResponse, body []byte, http gorequest.Response, err error) *CgiBinComponentGetPrivacySettingResult { - return &CgiBinComponentGetPrivacySettingResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinComponentGetPrivacySettingResult(result CgiBinComponentGetPrivacySettingResponse, body []byte, http gorequest.Response) *CgiBinComponentGetPrivacySettingResult { + return &CgiBinComponentGetPrivacySettingResult{Result: result, Body: body, Http: http} } // CgiBinComponentGetPrivacySetting 查询小程序用户隐私保护指引 // @privacyVer 1表示现网版本,即,传1则该接口返回的内容是现网版本的;2表示开发版,即,传2则该接口返回的内容是开发版本的。默认是2。 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/get_privacy_setting.html -func (c *Client) CgiBinComponentGetPrivacySetting(ctx context.Context, privacyVer int) *CgiBinComponentGetPrivacySettingResult { +func (c *Client) CgiBinComponentGetPrivacySetting(ctx context.Context, privacyVer int) (*CgiBinComponentGetPrivacySettingResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params["privacy_ver"] = privacyVer // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/component/getprivacysetting?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentGetPrivacySettingResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentGetPrivacySettingResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinComponentGetPrivacySettingResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.component.setprivacysetting.go b/service/wechatopen/cgi-bin.component.setprivacysetting.go index 693e2e23..bd15330b 100644 --- a/service/wechatopen/cgi-bin.component.setprivacysetting.go +++ b/service/wechatopen/cgi-bin.component.setprivacysetting.go @@ -17,24 +17,38 @@ type CgiBinComponentSetPrivacySettingResult struct { Result CgiBinComponentSetPrivacySettingResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinComponentSetPrivacySettingResult(result CgiBinComponentSetPrivacySettingResponse, body []byte, http gorequest.Response, err error) *CgiBinComponentSetPrivacySettingResult { - return &CgiBinComponentSetPrivacySettingResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinComponentSetPrivacySettingResult(result CgiBinComponentSetPrivacySettingResponse, body []byte, http gorequest.Response) *CgiBinComponentSetPrivacySettingResult { + return &CgiBinComponentSetPrivacySettingResult{Result: result, Body: body, Http: http} } // CgiBinComponentSetPrivacySetting 配置小程序用户隐私保护指引 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/set_privacy_setting.html -func (c *Client) CgiBinComponentSetPrivacySetting(ctx context.Context, notMustParams ...gorequest.Params) *CgiBinComponentSetPrivacySettingResult { +func (c *Client) CgiBinComponentSetPrivacySetting(ctx context.Context, notMustParams ...gorequest.Params) (*CgiBinComponentSetPrivacySettingResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/component/setprivacysetting?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinComponentSetPrivacySettingResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinComponentSetPrivacySettingResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinComponentSetPrivacySettingResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/cgi-bin.get_api_domain_ip.go b/service/wechatopen/cgi-bin.get_api_domain_ip.go index 04af3cfc..9e5de3f6 100644 --- a/service/wechatopen/cgi-bin.get_api_domain_ip.go +++ b/service/wechatopen/cgi-bin.get_api_domain_ip.go @@ -16,20 +16,27 @@ type GetCallBackIpResult struct { Result GetCallBackIpResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func NewGetCallBackIpResult(result GetCallBackIpResponse, body []byte, http gorequest.Response, err error) *GetCallBackIpResult { - return &GetCallBackIpResult{Result: result, Body: body, Http: http, Err: err} +func NewGetCallBackIpResult(result GetCallBackIpResponse, body []byte, http gorequest.Response) *GetCallBackIpResult { + return &GetCallBackIpResult{Result: result, Body: body, Http: http} } // CgiBinGetApiDomainIp 获取微信服务器IP地址 // https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_the_WeChat_server_IP_address.html -func (c *Client) CgiBinGetApiDomainIp(ctx context.Context, componentAccessToken string) *GetCallBackIpResult { +func (c *Client) CgiBinGetApiDomainIp(ctx context.Context, componentAccessToken string) (*GetCallBackIpResult, error) { + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/get_api_domain_ip?access_token=%s", componentAccessToken), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/get_api_domain_ip?access_token=%s", componentAccessToken), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response GetCallBackIpResponse err = json.Unmarshal(request.ResponseBody, &response) - return NewGetCallBackIpResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return NewGetCallBackIpResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.material.get_material.go b/service/wechatopen/cgi-bin.material.get_material.go new file mode 100644 index 00000000..6d8a093d --- /dev/null +++ b/service/wechatopen/cgi-bin.material.get_material.go @@ -0,0 +1,70 @@ +package wechatopen + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "github.com/dtapps/go-library/utils/gorequest" + "github.com/dtapps/go-library/utils/gostorage" + "net/http" +) + +type CgiBinMaterialGetMaterialResponse struct { + Errcode int `json:"errcode"` + Errmsg string `json:"errmsg"` +} + +type CgiBinMaterialGetMaterialResult struct { + Result CgiBinMaterialGetMaterialResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 +} + +func newCgiBinMaterialGetMaterialResult(result CgiBinMaterialGetMaterialResponse, body []byte, http gorequest.Response) *CgiBinMaterialGetMaterialResult { + return &CgiBinMaterialGetMaterialResult{Result: result, Body: body, Http: http} +} + +// CgiBinMaterialGetMaterial 获取永久素材 +// https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Getting_Permanent_Assets.html +func (c *Client) CgiBinMaterialGetMaterial(ctx context.Context, mediaId string) (*CgiBinMaterialGetMaterialResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() + params["media_id"] = mediaId // 要获取的素材的media_id + // 请求 + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/material/get_material?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } + // 定义 + var response CgiBinMaterialGetMaterialResponse + // 判断内容是否为图片 + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + // 可能是图片 + return newCgiBinMaterialGetMaterialResult(CgiBinMaterialGetMaterialResponse{}, request.ResponseBody, request), nil + } + return newCgiBinMaterialGetMaterialResult(response, request.ResponseBody, request), err +} + +func (cr *CgiBinMaterialGetMaterialResult) SaveImg(db *gostorage.AliYun, fileName, filePath string) error { + if cr.Result.Errcode != 0 { + return errors.New(cr.Result.Errmsg) + } + // 上传 + _, err := db.PutObject(bytes.NewReader(cr.Body), filePath, fileName) + if err != nil { + return err + } + return nil +} diff --git a/service/wechatopen/cgi-bin.open.sameentity.go b/service/wechatopen/cgi-bin.open.sameentity.go new file mode 100644 index 00000000..873e9471 --- /dev/null +++ b/service/wechatopen/cgi-bin.open.sameentity.go @@ -0,0 +1,48 @@ +package wechatopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type CgiBinOpenSameEnTityResponse struct { + Errcode int `json:"errcode"` + Errmsg string `json:"errmsg"` + SameEntity bool `json:"same_entity"` // 是否同主体;true表示同主体;false表示不同主体 +} + +type CgiBinOpenSameEnTityResult struct { + Result CgiBinOpenSameEnTityResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 +} + +func newCgiBinOpenSameEnTityResult(result CgiBinOpenSameEnTityResponse, body []byte, http gorequest.Response) *CgiBinOpenSameEnTityResult { + return &CgiBinOpenSameEnTityResult{Result: result, Body: body, Http: http} +} + +// CgiBinOpenSameEnTity 获取授权绑定的商户号列表 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/cloudbase-common/wechatpay/getWechatPayList.html +func (c *Client) CgiBinOpenSameEnTity(ctx context.Context) (*CgiBinOpenSameEnTityResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() + // 请求 + request, err := c.request(ctx, apiUrl+"/cgi-bin/open/sameentity?access_token="+c.GetComponentAccessToken(ctx), params, http.MethodGet) + if err != nil { + return nil, err + } + // 定义 + var response CgiBinOpenSameEnTityResponse + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + return newCgiBinOpenSameEnTityResult(response, request.ResponseBody, request), nil +} diff --git a/service/wechatopen/cgi-bin.shorturl.go b/service/wechatopen/cgi-bin.shorturl.go index 23c4794f..c140a930 100644 --- a/service/wechatopen/cgi-bin.shorturl.go +++ b/service/wechatopen/cgi-bin.shorturl.go @@ -18,16 +18,24 @@ type CgiBinShortUrlResult struct { Result CgiBinShortUrlResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinShortUrlResult(result CgiBinShortUrlResponse, body []byte, http gorequest.Response, err error) *CgiBinShortUrlResult { - return &CgiBinShortUrlResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinShortUrlResult(result CgiBinShortUrlResponse, body []byte, http gorequest.Response) *CgiBinShortUrlResult { + return &CgiBinShortUrlResult{Result: result, Body: body, Http: http} } // CgiBinShortUrl 将二维码长链接转成短链接 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/qrcode/shorturl.html -func (c *Client) CgiBinShortUrl(ctx context.Context, longUrl string) *CgiBinShortUrlResult { +func (c *Client) CgiBinShortUrl(ctx context.Context, longUrl string) (*CgiBinShortUrlResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params["action"] = "long2short" // 此处填long2short,代表长链接转短链接 @@ -37,5 +45,8 @@ func (c *Client) CgiBinShortUrl(ctx context.Context, longUrl string) *CgiBinShor // 定义 var response CgiBinShortUrlResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinShortUrlResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinShortUrlResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.wxopen.qrcodejumpadd.go b/service/wechatopen/cgi-bin.wxopen.qrcodejumpadd.go index 2102c02a..c021fd1c 100644 --- a/service/wechatopen/cgi-bin.wxopen.qrcodejumpadd.go +++ b/service/wechatopen/cgi-bin.wxopen.qrcodejumpadd.go @@ -17,24 +17,38 @@ type CgiBinWxOpenQrCodeJumpAddResult struct { Result CgiBinWxOpenQrCodeJumpAddResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinWxOpenQrCodeJumpAddResult(result CgiBinWxOpenQrCodeJumpAddResponse, body []byte, http gorequest.Response, err error) *CgiBinWxOpenQrCodeJumpAddResult { - return &CgiBinWxOpenQrCodeJumpAddResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinWxOpenQrCodeJumpAddResult(result CgiBinWxOpenQrCodeJumpAddResponse, body []byte, http gorequest.Response) *CgiBinWxOpenQrCodeJumpAddResult { + return &CgiBinWxOpenQrCodeJumpAddResult{Result: result, Body: body, Http: http} } // CgiBinWxOpenQrCodeJumpAdd 增加或修改二维码规则 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/qrcode/qrcodejumpadd.html -func (c *Client) CgiBinWxOpenQrCodeJumpAdd(ctx context.Context, notMustParams ...gorequest.Params) *CgiBinWxOpenQrCodeJumpAddResult { +func (c *Client) CgiBinWxOpenQrCodeJumpAdd(ctx context.Context, notMustParams ...gorequest.Params) (*CgiBinWxOpenQrCodeJumpAddResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/wxopen/qrcodejumpadd?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinWxOpenQrCodeJumpAddResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinWxOpenQrCodeJumpAddResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinWxOpenQrCodeJumpAddResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/cgi-bin.wxopen.qrcodejumpdelete.go b/service/wechatopen/cgi-bin.wxopen.qrcodejumpdelete.go index 9b69d1b6..68f70f35 100644 --- a/service/wechatopen/cgi-bin.wxopen.qrcodejumpdelete.go +++ b/service/wechatopen/cgi-bin.wxopen.qrcodejumpdelete.go @@ -17,23 +17,37 @@ type CgiBinWxOpenQrCodeJumpDeleteResult struct { Result CgiBinWxOpenQrCodeJumpDeleteResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinWxOpenQrCodeJumpDeleteResult(result CgiBinWxOpenQrCodeJumpDeleteResponse, body []byte, http gorequest.Response, err error) *CgiBinWxOpenQrCodeJumpDeleteResult { - return &CgiBinWxOpenQrCodeJumpDeleteResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinWxOpenQrCodeJumpDeleteResult(result CgiBinWxOpenQrCodeJumpDeleteResponse, body []byte, http gorequest.Response) *CgiBinWxOpenQrCodeJumpDeleteResult { + return &CgiBinWxOpenQrCodeJumpDeleteResult{Result: result, Body: body, Http: http} } // CgiBinWxOpenQrCodeJumpDelete 删除已设置的二维码规则 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/qrcode/qrcodejumpdelete.html -func (c *Client) CgiBinWxOpenQrCodeJumpDelete(ctx context.Context, prefix string) *CgiBinWxOpenQrCodeJumpDeleteResult { +func (c *Client) CgiBinWxOpenQrCodeJumpDelete(ctx context.Context, prefix string) (*CgiBinWxOpenQrCodeJumpDeleteResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params["prefix"] = prefix // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/wxopen/qrcodejumpdelete?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinWxOpenQrCodeJumpDeleteResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinWxOpenQrCodeJumpDeleteResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinWxOpenQrCodeJumpDeleteResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.wxopen.qrcodejumpdownloa.go b/service/wechatopen/cgi-bin.wxopen.qrcodejumpdownloa.go index ae36514d..ea737ce5 100644 --- a/service/wechatopen/cgi-bin.wxopen.qrcodejumpdownloa.go +++ b/service/wechatopen/cgi-bin.wxopen.qrcodejumpdownloa.go @@ -19,22 +19,36 @@ type CgiBinWxOpenQrCodeJumpDownloadResult struct { Result CgiBinWxOpenQrCodeJumpDownloadResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinWxOpenQrCodeJumpDownloadResult(result CgiBinWxOpenQrCodeJumpDownloadResponse, body []byte, http gorequest.Response, err error) *CgiBinWxOpenQrCodeJumpDownloadResult { - return &CgiBinWxOpenQrCodeJumpDownloadResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinWxOpenQrCodeJumpDownloadResult(result CgiBinWxOpenQrCodeJumpDownloadResponse, body []byte, http gorequest.Response) *CgiBinWxOpenQrCodeJumpDownloadResult { + return &CgiBinWxOpenQrCodeJumpDownloadResult{Result: result, Body: body, Http: http} } // CgiBinWxOpenQrCodeJumpDownload 获取校验文件名称及内容 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/qrcode/qrcodejumpdownload.html -func (c *Client) CgiBinWxOpenQrCodeJumpDownload(ctx context.Context) *CgiBinWxOpenQrCodeJumpDownloadResult { +func (c *Client) CgiBinWxOpenQrCodeJumpDownload(ctx context.Context) (*CgiBinWxOpenQrCodeJumpDownloadResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/wxopen/qrcodejumpdownload?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinWxOpenQrCodeJumpDownloadResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinWxOpenQrCodeJumpDownloadResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinWxOpenQrCodeJumpDownloadResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.wxopen.qrcodejumpget.go b/service/wechatopen/cgi-bin.wxopen.qrcodejumpget.go index 63bbbf21..f8e02eda 100644 --- a/service/wechatopen/cgi-bin.wxopen.qrcodejumpget.go +++ b/service/wechatopen/cgi-bin.wxopen.qrcodejumpget.go @@ -28,22 +28,36 @@ type CgiBinWxOpenQrCodeJumpGetResult struct { Result CgiBinWxOpenQrCodeJumpGetResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinWxOpenQrCodeJumpGetResult(result CgiBinWxOpenQrCodeJumpGetResponse, body []byte, http gorequest.Response, err error) *CgiBinWxOpenQrCodeJumpGetResult { - return &CgiBinWxOpenQrCodeJumpGetResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinWxOpenQrCodeJumpGetResult(result CgiBinWxOpenQrCodeJumpGetResponse, body []byte, http gorequest.Response) *CgiBinWxOpenQrCodeJumpGetResult { + return &CgiBinWxOpenQrCodeJumpGetResult{Result: result, Body: body, Http: http} } // CgiBinWxOpenQrCodeJumpGet 获取已设置的二维码规则 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/qrcode/qrcodejumpadd.html -func (c *Client) CgiBinWxOpenQrCodeJumpGet(ctx context.Context) *CgiBinWxOpenQrCodeJumpGetResult { +func (c *Client) CgiBinWxOpenQrCodeJumpGet(ctx context.Context) (*CgiBinWxOpenQrCodeJumpGetResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/wxopen/qrcodejumpget?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinWxOpenQrCodeJumpGetResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinWxOpenQrCodeJumpGetResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinWxOpenQrCodeJumpGetResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/cgi-bin.wxopen.qrcodejumppublish.go b/service/wechatopen/cgi-bin.wxopen.qrcodejumppublish.go index e0f9faf9..9c6973f8 100644 --- a/service/wechatopen/cgi-bin.wxopen.qrcodejumppublish.go +++ b/service/wechatopen/cgi-bin.wxopen.qrcodejumppublish.go @@ -17,25 +17,39 @@ type CgiBinWxOpenQrCodeJumpPublishResult struct { Result CgiBinWxOpenQrCodeJumpPublishResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newCgiBinWxOpenQrCodeJumpPublishResult(result CgiBinWxOpenQrCodeJumpPublishResponse, body []byte, http gorequest.Response, err error) *CgiBinWxOpenQrCodeJumpPublishResult { - return &CgiBinWxOpenQrCodeJumpPublishResult{Result: result, Body: body, Http: http, Err: err} +func newCgiBinWxOpenQrCodeJumpPublishResult(result CgiBinWxOpenQrCodeJumpPublishResponse, body []byte, http gorequest.Response) *CgiBinWxOpenQrCodeJumpPublishResult { + return &CgiBinWxOpenQrCodeJumpPublishResult{Result: result, Body: body, Http: http} } // CgiBinWxOpenQrCodeJumpPublish 发布已设置的二维码规则 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/qrcode/qrcodejumppublish.html -func (c *Client) CgiBinWxOpenQrCodeJumpPublish(ctx context.Context, prefix string) *CgiBinWxOpenQrCodeJumpPublishResult { +func (c *Client) CgiBinWxOpenQrCodeJumpPublish(ctx context.Context, prefix string) (*CgiBinWxOpenQrCodeJumpPublishResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params["prefix"] = prefix // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/cgi-bin/wxopen/qrcodejumppublish?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response CgiBinWxOpenQrCodeJumpPublishResponse err = json.Unmarshal(request.ResponseBody, &response) - return newCgiBinWxOpenQrCodeJumpPublishResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newCgiBinWxOpenQrCodeJumpPublishResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/check.go b/service/wechatopen/check.go new file mode 100644 index 00000000..92cb4aa5 --- /dev/null +++ b/service/wechatopen/check.go @@ -0,0 +1,21 @@ +package wechatopen + +func (c *Client) checkComponentIsConfig() error { + componentAppId := c.GetComponentAppId() + if componentAppId == "" { + return componentAppIdNoConfig + } + componentAppSecret := c.GetComponentAppSecret() + if componentAppSecret == "" { + return componentAppSecretNoConfig + } + return nil +} + +func (c *Client) checkAuthorizerIsConfig() error { + authorizerAppid := c.GetAuthorizerAppid() + if authorizerAppid == "" { + return authorizerAppidNoConfig + } + return nil +} diff --git a/service/wechatopen/client.go b/service/wechatopen/client.go index 257cff6b..11768dd6 100644 --- a/service/wechatopen/client.go +++ b/service/wechatopen/client.go @@ -4,72 +4,72 @@ import ( "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - ComponentAccessToken string // 第三方平台 access_token - ComponentVerifyTicket string // 微信后台推送的 ticket - PreAuthCode string // 预授权码 - AuthorizerAccessToken string // 接口调用令牌 - AuthorizerRefreshToken string // 刷新令牌 - AuthorizerAppid string // 授权方 appid - ComponentAppId string // 第三方平台 appid - ComponentAppSecret string // 第三方平台 app_secret - MessageToken string - MessageKey string - RedisClient *dorm.RedisClient // 缓存数据库 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// 缓存前缀 +// wechat_open:component_verify_ticket: +// wechat_open:component_access_token: +// wechat_open:authorizer_access_token: +// wechat_open:pre_auth_code: +type redisCachePrefixFun func() (componentVerifyTicket, componentAccessToken, authorizerAccessToken, preAuthCode string) + +// ClientConfig 实例配置 +type ClientConfig struct { + AuthorizerAppid string // 授权方 appid + ComponentAppId string // 第三方平台 appid + ComponentAppSecret string // 第三方平台 app_secret + MessageToken string + MessageKey string + RedisClient *dorm.RedisClient // 缓存数据库 + RedisCachePrefixFun redisCachePrefixFun // 缓存前缀 } -// Client 微信公众号服务 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + componentAccessToken string // 第三方平台 access_token + componentVerifyTicket string // 微信后台推送的 ticket + preAuthCode string // 预授权码 + authorizerAccessToken string // 接口调用令牌 + authorizerRefreshToken string // 刷新令牌 + authorizerAppid string // 授权方 appid + componentAppId string // 第三方平台appid + componentAppSecret string // 第三方平台app_secret + messageToken string + messageKey string + } + cache struct { + redisClient *dorm.RedisClient // 缓存数据库 + componentVerifyTicketPrefix string + componentAccessTokenPrefix string + authorizerAccessTokenPrefix string + preAuthCodePrefix string + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.componentAppId = config.ComponentAppId + c.config.componentAppSecret = config.ComponentAppSecret + c.config.messageToken = config.MessageToken + c.config.messageKey = config.MessageKey - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() - return c, nil -} + c.cache.redisClient = config.RedisClient -// ConfigComponent 配置 -func (c *Client) ConfigComponent(componentAppId, componentAppSecret string) *Client { - c.config.ComponentAppId = componentAppId - c.config.ComponentAppSecret = componentAppSecret - return c -} + c.cache.componentVerifyTicketPrefix, c.cache.componentAccessTokenPrefix, c.cache.authorizerAccessTokenPrefix, c.cache.preAuthCodePrefix = config.RedisCachePrefixFun() + if c.cache.componentVerifyTicketPrefix == "" || c.cache.componentAccessTokenPrefix == "" || c.cache.authorizerAccessTokenPrefix == "" || c.cache.preAuthCodePrefix == "" { + return nil, redisCachePrefixNoConfig + } -// ConfigAuthorizer 配置第三方 -func (c *Client) ConfigAuthorizer(authorizerAppid string) *Client { - c.config.AuthorizerAppid = authorizerAppid - return c + return c, nil } diff --git a/service/wechatopen/config.go b/service/wechatopen/config.go new file mode 100644 index 00000000..9189abb3 --- /dev/null +++ b/service/wechatopen/config.go @@ -0,0 +1,25 @@ +package wechatopen + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigComponent 配置 +func (c *Client) ConfigComponent(componentAppId, componentAppSecret string) *Client { + c.config.componentAppId = componentAppId + c.config.componentAppSecret = componentAppSecret + return c +} + +// ConfigAuthorizer 配置第三方 +func (c *Client) ConfigAuthorizer(authorizerAppid string) *Client { + c.config.authorizerAppid = authorizerAppid + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatopen/const.go b/service/wechatopen/const.go index cc418a17..539b58af 100644 --- a/service/wechatopen/const.go +++ b/service/wechatopen/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "wechatopen" + LogTable = "wechatopen" ) diff --git a/service/wechatopen/error.go b/service/wechatopen/error.go new file mode 100644 index 00000000..04c267a6 --- /dev/null +++ b/service/wechatopen/error.go @@ -0,0 +1,16 @@ +package wechatopen + +import "errors" + +var ( + redisCachePrefixNoConfig = errors.New("请配置 RedisCachePrefix") +) + +var ( + componentAppIdNoConfig = errors.New("请配置 ComponentAppId") + componentAppSecretNoConfig = errors.New("请配置 ComponentAppSecret") +) + +var ( + authorizerAppidNoConfig = errors.New("请配置 AuthorizerAppid 或 ConfigAuthorizer") +) diff --git a/service/wechatopen/get.go b/service/wechatopen/get.go index 46a23cce..ffad4258 100644 --- a/service/wechatopen/get.go +++ b/service/wechatopen/get.go @@ -1,5 +1,47 @@ package wechatopen +import "github.com/dtapps/go-library/utils/golog" + +//func (c *Client) GetComponentAccessToken() string { +// return c.config.componentAccessToken +//} + +//func (c *Client) GetComponentVerifyTicket() string { +// return c.config.componentVerifyTicket +//} + +//func (c *Client) GetPreAuthCode() string { +// return c.config.preAuthCode +//} + +//func (c *Client) GetAuthorizerAccessToken() string { +// return c.config.authorizerAccessToken +//} + +func (c *Client) GetAuthorizerRefreshToken() string { + return c.config.authorizerRefreshToken +} + +func (c *Client) GetAuthorizerAppid() string { + return c.config.authorizerAppid +} + func (c *Client) GetComponentAppId() string { - return c.config.ComponentAppId + return c.config.componentAppId +} + +func (c *Client) GetComponentAppSecret() string { + return c.config.componentAppSecret +} + +func (c *Client) GetMessageToken() string { + return c.config.messageToken +} + +func (c *Client) GetMessageKey() string { + return c.config.messageKey +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/wechatopen/redis.go b/service/wechatopen/redis.go index f5050d1a..2ae4e571 100644 --- a/service/wechatopen/redis.go +++ b/service/wechatopen/redis.go @@ -2,13 +2,12 @@ package wechatopen import ( "context" - "fmt" "time" ) // 微信后台推送的ticke func (c *Client) getComponentVerifyTicketCacheKeyName() string { - return fmt.Sprintf("wechat_open:component_verify_ticket:%v", c.config.ComponentAppId) + return c.cache.componentVerifyTicketPrefix + c.GetComponentAppId() } // SetComponentVerifyTicket 设置微信后台推送的ticke @@ -16,22 +15,22 @@ func (c *Client) SetComponentVerifyTicket(ctx context.Context, componentVerifyTi if componentVerifyTicket == "" { return "" } - c.config.RedisClient.Set(ctx, c.getComponentVerifyTicketCacheKeyName(), componentVerifyTicket, time.Hour*12) + c.cache.redisClient.Set(ctx, c.getComponentVerifyTicketCacheKeyName(), componentVerifyTicket, time.Hour*12) return c.GetComponentVerifyTicket(ctx) } // GetComponentVerifyTicket 获取微信后台推送的ticke func (c *Client) GetComponentVerifyTicket(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.ComponentVerifyTicket + if c.cache.redisClient.Db == nil { + return c.config.componentVerifyTicket } - result, _ := c.config.RedisClient.Get(ctx, c.getComponentVerifyTicketCacheKeyName()).Result() + result, _ := c.cache.redisClient.Get(ctx, c.getComponentVerifyTicketCacheKeyName()).Result() return result } // 令牌 func (c *Client) getComponentAccessTokenCacheKeyName() string { - return fmt.Sprintf("wechat_open:component_access_token:%v", c.config.ComponentAppId) + return c.cache.componentAccessTokenPrefix + c.GetComponentAppId() } // SetComponentAccessToken 设置令牌 @@ -39,35 +38,39 @@ func (c *Client) SetComponentAccessToken(ctx context.Context, componentAccessTok if componentAccessToken == "" { return "" } - c.config.RedisClient.Set(ctx, c.getComponentAccessTokenCacheKeyName(), componentAccessToken, time.Second*7200) + c.cache.redisClient.Set(ctx, c.getComponentAccessTokenCacheKeyName(), componentAccessToken, time.Second*7200) return c.GetComponentAccessToken(ctx) } // GetComponentAccessToken 获取令牌 func (c *Client) GetComponentAccessToken(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.ComponentAccessToken + if c.cache.redisClient.Db == nil { + return c.config.componentAccessToken } - result, _ := c.config.RedisClient.Db.Get(ctx, c.getComponentAccessTokenCacheKeyName()).Result() + result, _ := c.cache.redisClient.Db.Get(ctx, c.getComponentAccessTokenCacheKeyName()).Result() return result } // MonitorComponentAccessToken 监控令牌 -func (c *Client) MonitorComponentAccessToken(ctx context.Context) string { +func (c *Client) MonitorComponentAccessToken(ctx context.Context) (string, error) { // 查询 componentAccessToken := c.GetComponentAccessToken(ctx) // 判断 - result := c.CgiBinGetApiDomainIp(ctx, componentAccessToken) + result, err := c.CgiBinGetApiDomainIp(ctx, componentAccessToken) + if err != nil { + return "", err + } if len(result.Result.IpList) > 0 { - return componentAccessToken + return componentAccessToken, err } // 重新获取 - return c.SetComponentAccessToken(ctx, c.CgiBinComponentApiComponentToken(ctx).Result.ComponentAccessToken) + resp, err := c.CgiBinComponentApiComponentToken(ctx) + return c.SetComponentAccessToken(ctx, resp.Result.ComponentAccessToken), err } // 授权方令牌 func (c *Client) getAuthorizerAccessTokenCacheKeyName() string { - return fmt.Sprintf("wechat_open:authorizer_access_token:%v:%v", c.config.ComponentAppId, c.config.AuthorizerAppid) + return c.cache.authorizerAccessTokenPrefix + c.GetComponentAppId() + ":" + c.GetAuthorizerAppid() } // SetAuthorizerAccessToken 设置授权方令牌 @@ -75,34 +78,35 @@ func (c *Client) SetAuthorizerAccessToken(ctx context.Context, authorizerAccessT if authorizerAccessToken == "" { return "" } - c.config.RedisClient.Set(ctx, c.getAuthorizerAccessTokenCacheKeyName(), authorizerAccessToken, time.Hour*2) + c.cache.redisClient.Set(ctx, c.getAuthorizerAccessTokenCacheKeyName(), authorizerAccessToken, time.Hour*2) return c.GetComponentAccessToken(ctx) } // GetAuthorizerAccessToken 获取授权方令牌 func (c *Client) GetAuthorizerAccessToken(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.AuthorizerAccessToken + if c.cache.redisClient.Db == nil { + return c.config.authorizerAccessToken } - result, _ := c.config.RedisClient.Get(ctx, c.getAuthorizerAccessTokenCacheKeyName()).Result() + result, _ := c.cache.redisClient.Get(ctx, c.getAuthorizerAccessTokenCacheKeyName()).Result() return result } // MonitorAuthorizerAccessToken 监控授权方令牌 -func (c *Client) MonitorAuthorizerAccessToken(ctx context.Context, authorizerRefreshToken string) string { +func (c *Client) MonitorAuthorizerAccessToken(ctx context.Context, authorizerRefreshToken string) (string, error) { // 查询 authorizerAccessToken := c.GetAuthorizerAccessToken(ctx) // 判断 if authorizerAccessToken != "" { - return authorizerAccessToken + return authorizerAccessToken, nil } // 重新获取 - return c.SetAuthorizerAccessToken(ctx, c.CgiBinComponentApiAuthorizerToken(ctx, authorizerRefreshToken).Result.AuthorizerAccessToken) + resp, err := c.CgiBinComponentApiAuthorizerToken(ctx, authorizerRefreshToken) + return c.SetAuthorizerAccessToken(ctx, resp.Result.AuthorizerAccessToken), err } // 预授权码 func (c *Client) getPreAuthCodeCacheKeyName() string { - return fmt.Sprintf("wechat_open:pre_auth_code:%v", c.config.ComponentAppId) + return c.cache.preAuthCodePrefix + c.GetComponentAppId() } // SetPreAuthCode 设置预授权码 @@ -110,32 +114,33 @@ func (c *Client) SetPreAuthCode(ctx context.Context, preAuthCode string) string if preAuthCode == "" { return "" } - c.config.RedisClient.Set(ctx, c.getPreAuthCodeCacheKeyName(), preAuthCode, time.Second*1700) + c.cache.redisClient.Set(ctx, c.getPreAuthCodeCacheKeyName(), preAuthCode, time.Second*1700) return c.GetComponentAccessToken(ctx) } // GetPreAuthCode 获取预授权码 func (c *Client) GetPreAuthCode(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.AuthorizerAccessToken + if c.cache.redisClient.Db == nil { + return c.config.authorizerAccessToken } - result, _ := c.config.RedisClient.Get(ctx, c.getPreAuthCodeCacheKeyName()).Result() + result, _ := c.cache.redisClient.Get(ctx, c.getPreAuthCodeCacheKeyName()).Result() return result } // DelPreAuthCode 删除预授权码 func (c *Client) DelPreAuthCode(ctx context.Context) error { - return c.config.RedisClient.Del(ctx, c.getPreAuthCodeCacheKeyName()).Err() + return c.cache.redisClient.Del(ctx, c.getPreAuthCodeCacheKeyName()).Err() } // MonitorPreAuthCode 监控预授权码 -func (c *Client) MonitorPreAuthCode(ctx context.Context) string { +func (c *Client) MonitorPreAuthCode(ctx context.Context) (string, error) { // 查询 preAuthCode := c.GetPreAuthCode(ctx) // 判断 if preAuthCode != "" { - return preAuthCode + return preAuthCode, nil } // 重新获取 - return c.SetPreAuthCode(ctx, c.CgiBinComponentApiCreatePreAuthCoden(ctx).Result.PreAuthCode) + resp, err := c.CgiBinComponentApiCreatePreAuthCoden(ctx) + return c.SetPreAuthCode(ctx, resp.Result.PreAuthCode), err } diff --git a/service/wechatopen/request.go b/service/wechatopen/request.go index bccd3a66..c77b0be9 100644 --- a/service/wechatopen/request.go +++ b/service/wechatopen/request.go @@ -9,7 +9,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (resp gorequest.Response, err error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -20,6 +20,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置格式 client.SetContentTypeJson() + // 设置用户代理 + client.SetUserAgent(gorequest.GetRandomUserAgentSystem()) + // 设置参数 client.SetParams(params) @@ -29,12 +32,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/wechatopen/service_http.authorizer_appid.go b/service/wechatopen/service_http.authorizer_appid.go index 35602271..1f5b86bb 100644 --- a/service/wechatopen/service_http.authorizer_appid.go +++ b/service/wechatopen/service_http.authorizer_appid.go @@ -25,7 +25,10 @@ func (c *Client) ServeHttpAuthorizerAppid(ctx context.Context, r *http.Request) return resp, agentUserId, errors.New("找不到过期时间参数") } - info := c.CgiBinComponentApiQueryAuth(ctx, authCode) + info, err := c.CgiBinComponentApiQueryAuth(ctx, authCode) + if err != nil { + return resp, agentUserId, err + } if info.Result.AuthorizationInfo.AuthorizerAppid == "" { return resp, agentUserId, errors.New("获取失败") } diff --git a/service/wechatopen/service_http.gin.go b/service/wechatopen/service_http.gin.go new file mode 100644 index 00000000..dc8dc752 --- /dev/null +++ b/service/wechatopen/service_http.gin.go @@ -0,0 +1,41 @@ +package wechatopen + +import ( + "context" + "github.com/gin-gonic/gin" +) + +// ResponseServeHttpGin 推送信息 +type ResponseServeHttpGin struct { + MsgSignature string // 签名串,对应 URL 参数的msg_signature + Timestamp string // 时间戳,对应 URL 参数的timestamp + Nonce string // 随机串,对应 URL 参数的nonce + Signature string + EncryptType string // 加密类型 + AppId string // 第三方平台 appid + Encrypt string // 加密内容 +} + +// ServeHttpGin 验证票据推送 +func (c *Client) ServeHttpGin(ctx context.Context, ginCtx *gin.Context) (ResponseServeHttpGin, error) { + + query := ginCtx.Request.URL.Query() + + // 声明接收的变量 + var validateJson struct { + AppId string `form:"AppId" json:"AppId" xml:"AppId" uri:"AppId" binding:"omitempty"` // 第三方平台 appid + Encrypt string `form:"Encrypt" json:"Encrypt" xml:"Encrypt" uri:"Encrypt" binding:"omitempty"` // 加密内容 + } + + err := ginCtx.ShouldBind(&validateJson) + + return ResponseServeHttpGin{ + MsgSignature: query.Get("msg_signature"), + Timestamp: query.Get("timestamp"), + Nonce: query.Get("nonce"), + Signature: query.Get("signature"), + EncryptType: query.Get("encrypt_type"), + AppId: validateJson.AppId, + Encrypt: validateJson.Encrypt, + }, err +} diff --git a/service/wechatopen/service_http.verify_ticket.go b/service/wechatopen/service_http.verify_ticket.go index b6d635e0..408ef30c 100644 --- a/service/wechatopen/service_http.verify_ticket.go +++ b/service/wechatopen/service_http.verify_ticket.go @@ -58,7 +58,7 @@ func (c *Client) ServeHttpVerifyTicket(ctx context.Context, r *http.Request) (re return resp, errors.New("未找到随机数参数") } - wantSignature = Sign(c.config.MessageToken, timestamp, nonce) + wantSignature = Sign(c.GetMessageToken(), timestamp, nonce) if haveSignature != wantSignature { return resp, errors.New("签名错误") } @@ -97,7 +97,7 @@ func (c *Client) ServeHttpVerifyTicket(ctx context.Context, r *http.Request) (re return resp, errors.New(fmt.Sprintf("Encrypt 解码字符串错误:%v", err)) } - AesKey, err := base64.StdEncoding.DecodeString(c.config.MessageKey + "=") + AesKey, err := base64.StdEncoding.DecodeString(c.GetMessageKey() + "=") if err != nil { return resp, errors.New(fmt.Sprintf("messageKey 解码字符串错误:%v", err)) } diff --git a/service/wechatopen/set.go b/service/wechatopen/set.go deleted file mode 100644 index 50a98cde..00000000 --- a/service/wechatopen/set.go +++ /dev/null @@ -1,7 +0,0 @@ -package wechatopen - -// SetAuthorizerAppid 设置代理商小程序 -func (c *Client) SetAuthorizerAppid(authorizerAppid string) { - c.config.AuthorizerAppid = authorizerAppid - return -} diff --git a/service/wechatopen/sign.decrypt.go b/service/wechatopen/sign.decrypt.go new file mode 100644 index 00000000..2f20a917 --- /dev/null +++ b/service/wechatopen/sign.decrypt.go @@ -0,0 +1,82 @@ +package wechatopen + +import ( + "context" + "encoding/base64" + "encoding/xml" + "errors" + "fmt" + "strings" +) + +// SignDecrypt 解密 +// ctx 上下文 +// params 入参 +// strXml 反射结构体 +// resp 加密数据 +// err 错误信息 +func (c *Client) SignDecrypt(ctx context.Context, params SignDecryptParams, strXml interface{}) (resp []byte, err error) { + + if params.Signature == "" { + return nil, errors.New("找不到签名参数") + } + + if params.Timestamp == "" { + return nil, errors.New("找不到时间戳参数") + } + + if params.Nonce == "" { + return nil, errors.New("未找到随机数参数") + } + + wantSignature := Sign(c.GetMessageToken(), params.Timestamp, params.Nonce) + if params.Signature != wantSignature { + return nil, errors.New("签名错误") + } + + // 进入事件执行 + if params.EncryptType != "aes" { + return nil, errors.New("未知的加密类型: " + params.EncryptType) + } + if params.Encrypt == "" { + return nil, errors.New("找不到签名参数") + } + + cipherData, err := base64.StdEncoding.DecodeString(params.Encrypt) + if err != nil { + return nil, errors.New(fmt.Sprintf("Encrypt 解码字符串错误:%v", err)) + } + + AesKey, err := base64.StdEncoding.DecodeString(c.GetMessageKey() + "=") + if err != nil { + return nil, errors.New(fmt.Sprintf("messageKey 解码字符串错误:%v", err)) + } + + msg, err := AesDecrypt(cipherData, AesKey) + if err != nil { + return nil, errors.New(fmt.Sprintf("AES解密错误:%v", err)) + } + + str := string(msg) + + left := strings.Index(str, "") + if left <= 0 { + return nil, errors.New(fmt.Sprintf("匹配不到:%v", left)) + } + right := strings.Index(str, "") + if right <= 0 { + return nil, errors.New(fmt.Sprintf("匹配不到:%v", right)) + } + msgStr := str[left:right] + if len(msgStr) == 0 { + return nil, errors.New(fmt.Sprintf("提取错误:%v", msgStr)) + } + + strByte := []byte(msgStr + "") + err = xml.Unmarshal(strByte, strXml) + if err != nil { + return nil, errors.New(fmt.Sprintf("解析错误:%v", err)) + } + + return strByte, nil +} diff --git a/service/wechatopen/sign.decrypt.params.go b/service/wechatopen/sign.decrypt.params.go new file mode 100644 index 00000000..99117b8f --- /dev/null +++ b/service/wechatopen/sign.decrypt.params.go @@ -0,0 +1,12 @@ +package wechatopen + +// SignDecryptParams 入参 +type SignDecryptParams struct { + Signature string // 签名串,对应 URL 参数的msg_signature + Timestamp string // 时间戳,对应 URL 参数的timestamp + Nonce string // 随机串,对应 URL 参数的nonce + EncryptType string // 加密类型 + MsgSignature string + AppId string // 第三方平台 appid + Encrypt string // 加密内容 +} diff --git a/service/wechatopen/sign.decrypt.response.go b/service/wechatopen/sign.decrypt.response.go new file mode 100644 index 00000000..a04b34b1 --- /dev/null +++ b/service/wechatopen/sign.decrypt.response.go @@ -0,0 +1,129 @@ +package wechatopen + +import "encoding/xml" + +// SignDecryptComponentVerifyTicket 验证票据 +// https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/component_verify_ticket.html +type SignDecryptComponentVerifyTicket struct { + XMLName xml.Name + AppId string `xml:"appId,omitempty"` // 第三方平台 appid + CreateTime int64 `xml:"CreateTime,omitempty"` // 时间戳,单位:s + InfoType string `xml:"InfoType,omitempty"` // 固定为:"component_verify_ticket" + ComponentVerifyTicket string `xml:"ComponentVerifyTicket,omitempty"` // Ticket 内容 +} + +// SignDecryptAuthorizeEvent 授权变更通知推送 +// https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/authorize_event.html +type SignDecryptAuthorizeEvent struct { + XMLName xml.Name + AppId string `xml:"appId,omitempty"` // 第三方平台 appid + CreateTime int64 `xml:"CreateTime,omitempty"` // 时间戳,单位:s + InfoType string `xml:"InfoType,omitempty"` // 通知类型 unauthorized=取消授权 updateauthorized=更新授权 authorized=授权成功 + AuthorizerAppid string `xml:"AuthorizerAppid,omitempty"` // 公众号或小程序的 appid + AuthorizationCode string `xml:"AuthorizationCode,omitempty"` // 授权码,可用于获取授权信息 + AuthorizationCodeExpiredTime string `xml:"AuthorizationCodeExpiredTime,omitempty"` // 授权码过期时间 单位秒 + PreAuthCode string `xml:"PreAuthCode,omitempty"` // 预授权码 +} + +// SignDecryptNotifyThirdFasteRegister 快速注册企业/个人小程序 +// https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Register_Mini_Programs/Fast_Registration_Interface_document.html +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/register-management/fast-registration-ind/fastRegisterPersonalMp.html +type SignDecryptNotifyThirdFasteRegister struct { + XMLName xml.Name + AppId string `xml:"AppId,omitempty"` // 第三方平台 appid + CreateTime int64 `xml:"CreateTime,omitempty"` // 时间戳,单位:s + InfoType string `xml:"InfoType,omitempty"` // 类型 + Appid string `xml:"appid,omitempty"` // 创建小程序appid + Status int64 `xml:"status,omitempty"` // 状态 + AuthCode string `xml:"auth_code,omitempty"` // 第三方授权码 + Msg string `xml:"msg,omitempty"` // 信息 + Info struct { + Name string `xml:"name,omitempty"` // 企业名称 + Code string `xml:"code,omitempty"` // 企业代码 + CodeType string `xml:"code_type,omitempty"` + LegalPersonaWechat string `xml:"legal_persona_wechat,omitempty"` // (企业)法人微信号 + LegalPersonaName string `xml:"legal_persona_name,omitempty"` // (企业)法人姓名 + ComponentPhone string `xml:"component_phone,omitempty"` // (企业/个人)第三方联系电话 + Wxuser string `xml:"wxuser"` // (个人)用户微信号 + Idname string `xml:"idname"` // (个人)用户姓名 + } `xml:"info,omitempty"` +} + +// SignDecryptNotifyThirdFastRegisterBetaApp 注册试用小程序 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/register-management/fast-regist-beta/registerBetaMiniprogram.html +type SignDecryptNotifyThirdFastRegisterBetaApp struct { + XMLName xml.Name + AppId string `xml:"AppId,omitempty"` // 第三方平台 appid + CreateTime int64 `xml:"CreateTime,omitempty"` // 时间戳,单位:s + InfoType string `xml:"InfoType,omitempty"` // 类型 + Appid string `xml:"appid,omitempty"` // 创建小程序appid + Status int64 `xml:"status,omitempty"` // 状态 + Msg string `xml:"msg,omitempty"` // 信息 + Info struct { + UniqueId string `xml:"unique_id,omitempty"` + Name string `xml:"name,omitempty"` // 小程序名称 + } `xml:"info,omitempty"` +} + +// SignDecryptNotifyThirdFastVerifyBetaApp 试用小程序快速认证 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/register-management/fast-regist-beta/verfifyBetaMiniprogram.html +type SignDecryptNotifyThirdFastVerifyBetaApp struct { + XMLName xml.Name + AppId string `xml:"AppId,omitempty"` // 第三方平台 appid + CreateTime int64 `xml:"CreateTime,omitempty"` // 时间戳,单位:s + InfoType string `xml:"InfoType,omitempty"` // 类型 + Appid string `xml:"appid,omitempty"` // 创建小程序appid + Status int64 `xml:"status,omitempty"` // 状态 + Msg string `xml:"msg,omitempty"` // 信息 + Info struct { + Name string `xml:"name,omitempty"` // 企业名称 + Code string `xml:"code,omitempty"` // 企业代码 + CodeType string `xml:"code_type,omitempty"` + LegalPersonaWechat string `xml:"legal_persona_wechat,omitempty"` // 法人微信号 + LegalPersonaName string `xml:"legal_persona_name,omitempty"` // 法人姓名 + ComponentPhone string `xml:"component_phone,omitempty"` // 第三方联系电话 + } `xml:"info,omitempty"` +} + +// SignDecryptWxaNicknameAudit 名称审核结果事件推送 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/basic-info-management/setNickName.html +type SignDecryptWxaNicknameAudit struct { + XMLName xml.Name + ToUserName string `xml:"ToUserName,omitempty"` // 小程序的原始 ID + FromUserName string `xml:"FromUserName,omitempty"` // 发送方帐号(一个 OpenID,此时发送方是系统帐号) + CreateTime int64 `xml:"CreateTime,omitempty"` // 消息创建时间 (整型),时间戳 + MsgType string `xml:"MsgType,omitempty"` // 消息类型 event + Event string `xml:"Event,omitempty"` // 事件类型 + Ret string `xml:"ret,omitempty"` // 审核结果 2:失败,3:成功 + Nickname string `xml:"nickname,omitempty"` // 需要更改的昵称 + Reason string `xml:"reason,omitempty"` // 审核失败的驳回原因 +} + +// SignDecryptWeAppAudit 代码审核结果推送 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/code-management/submitAudit.html +type SignDecryptWeAppAudit struct { + XMLName xml.Name + ToUserName string `xml:"ToUserName,omitempty"` // 小程序的原始 ID + FromUserName string `xml:"FromUserName,omitempty"` // 发送方帐号(一个 OpenID,此时发送方是系统帐号) + CreateTime int64 `xml:"CreateTime,omitempty"` // 消息创建时间 (整型),时间戳 + MsgType string `xml:"MsgType,omitempty"` // 消息类型 event + Event string `xml:"Event,omitempty"` // 事件类型 weapp_audit_success=审核通过 weapp_audit_fail=审核不通过 weapp_audit_delay=审核延后 + SuccTime int64 `xml:"SuccTime,omitempty"` // 审核成功时的时间戳 + FailTime int64 `xml:"FailTime,omitempty"` // 审核不通过的时间戳 + DelayTime int64 `xml:"DelayTime,omitempty"` // 审核延后时的时间戳 + Reason string `xml:"reason,omitempty"` // 审核不通过的原因 + ScreenShot string `xml:"ScreenShot,omitempty"` // 审核不通过的截图示例。用 | 分隔的 media_id 的列表,可通过获取永久素材接口拉取截图内容 +} + +// SignDecryptWxaSecurityApplySetOrderPathInfo 申请设置订单页 path 信息 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/basic-info-management/applySetOrderPathInfo.html +type SignDecryptWxaSecurityApplySetOrderPathInfo struct { + XMLName xml.Name + List string `xml:"List,omitempty"` // 申请结果列表 + Appid string `xml:"Appid,omitempty"` // 申请的appid + AuditId string `xml:"AuditId,omitempty"` // 审核单id + Status string `xml:"Status,omitempty"` // 订单页 path 状态 + ApplyTime int64 `xml:"ApplyTime,omitempty"` // 申请时间 + AuditTime int64 `xml:"AuditTime,omitempty"` // 审核时间 + Reason string `xml:"Reason,omitempty"` // 审核原因 +} diff --git a/service/wechatopen/sns.component.jscode2session.go b/service/wechatopen/sns.component.jscode2session.go index 340ec772..32c251c0 100644 --- a/service/wechatopen/sns.component.jscode2session.go +++ b/service/wechatopen/sns.component.jscode2session.go @@ -22,29 +22,43 @@ type SnsComponentJsCode2sessionResult struct { Result SnsComponentJsCode2sessionResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newSnsComponentJsCode2sessionResult(result SnsComponentJsCode2sessionResponse, body []byte, http gorequest.Response, err error) *SnsComponentJsCode2sessionResult { - return &SnsComponentJsCode2sessionResult{Result: result, Body: body, Http: http, Err: err} +func newSnsComponentJsCode2sessionResult(result SnsComponentJsCode2sessionResponse, body []byte, http gorequest.Response) *SnsComponentJsCode2sessionResult { + return &SnsComponentJsCode2sessionResult{Result: result, Body: body, Http: http} } // SnsComponentJsCode2session 小程序登录 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/others/WeChat_login.html -func (c *Client) SnsComponentJsCode2session(ctx context.Context, jsCode string) *SnsComponentJsCode2sessionResult { +func (c *Client) SnsComponentJsCode2session(ctx context.Context, jsCode string) (*SnsComponentJsCode2sessionResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() - params["appid"] = c.config.AuthorizerAppid // 小程序的 appId + params["appid"] = c.GetAuthorizerAppid() // 小程序的 appId params["js_code"] = jsCode // wx.login 获取的 code params["grant_type"] = "authorization_code" // 填 authorization_code - params["component_appid"] = c.config.ComponentAppId // 第三方平台 appid + params["component_appid"] = c.GetComponentAppId() // 第三方平台 appid params["component_access_token"] = c.GetComponentAccessToken(ctx) // 第三方平台的component_access_token // 请求 request, err := c.request(ctx, apiUrl+"/sns/component/jscode2session", params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response SnsComponentJsCode2sessionResponse err = json.Unmarshal(request.ResponseBody, &response) - return newSnsComponentJsCode2sessionResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newSnsComponentJsCode2sessionResult(response, request.ResponseBody, request), nil } type UserInfo struct { @@ -73,7 +87,7 @@ type UserInfoResult struct { } func newUserInfoResult(result UserInfoResponse, err error) *UserInfoResult { - return &UserInfoResult{Result: result, Err: err} + return &UserInfoResult{Result: result} } // UserInfo 解密用户信息 diff --git a/service/wechatopen/tcb.wxpaylist.go b/service/wechatopen/tcb.wxpaylist.go index 831f0211..bc7b7cff 100644 --- a/service/wechatopen/tcb.wxpaylist.go +++ b/service/wechatopen/tcb.wxpaylist.go @@ -24,24 +24,35 @@ type TckWxPayListResult struct { Result TckWxPayListResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newTckWxPayListResult(result TckWxPayListResponse, body []byte, http gorequest.Response, err error) *TckWxPayListResult { - return &TckWxPayListResult{Result: result, Body: body, Http: http, Err: err} +func newTckWxPayListResult(result TckWxPayListResponse, body []byte, http gorequest.Response) *TckWxPayListResult { + return &TckWxPayListResult{Result: result, Body: body, Http: http} } // TckWxPayList 获取授权绑定的商户号列表 // https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/cloudbase-common/wechatpay/getWechatPayList.html -func (c *Client) TckWxPayList(ctx context.Context) *TckWxPayListResult { +func (c *Client) TckWxPayList(ctx context.Context) (*TckWxPayListResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 // 参数 params := gorequest.NewParams() // 请求 request, err := c.request(ctx, apiUrl+"/tcb/wxpaylist?access_token="+c.GetComponentAccessToken(ctx), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response TckWxPayListResponse err = json.Unmarshal(request.ResponseBody, &response) - return newTckWxPayListResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newTckWxPayListResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.addtotemplate.go b/service/wechatopen/wxa.addtotemplate.go index 528bfae8..37a6756b 100644 --- a/service/wechatopen/wxa.addtotemplate.go +++ b/service/wechatopen/wxa.addtotemplate.go @@ -17,26 +17,36 @@ type WxaAddToTemplateResult struct { Result WxaAddToTemplateResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaAddToTemplateResult(result WxaAddToTemplateResponse, body []byte, http gorequest.Response, err error) *WxaAddToTemplateResult { - return &WxaAddToTemplateResult{Result: result, Body: body, Http: http, Err: err} +func newWxaAddToTemplateResult(result WxaAddToTemplateResponse, body []byte, http gorequest.Response) *WxaAddToTemplateResult { + return &WxaAddToTemplateResult{Result: result, Body: body, Http: http} } // WxaAddToTemplate 将草稿添加到代码模板库 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/code_template/addtotemplate.html -func (c *Client) WxaAddToTemplate(ctx context.Context, draftId string, templateType int) *WxaAddToTemplateResult { +func (c *Client) WxaAddToTemplate(ctx context.Context, draftId string, templateType int) (*WxaAddToTemplateResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params["draft_id"] = draftId params["template_type"] = templateType // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/addtotemplate?access_token=%s", c.GetComponentAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaAddToTemplateResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaAddToTemplateResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaAddToTemplateResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.bind_tester.go b/service/wechatopen/wxa.bind_tester.go index c28df13a..3bb9dbb3 100644 --- a/service/wechatopen/wxa.bind_tester.go +++ b/service/wechatopen/wxa.bind_tester.go @@ -18,25 +18,39 @@ type WxaBindTesterResult struct { Result WxaBindTesterResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaBindTesterResult(result WxaBindTesterResponse, body []byte, http gorequest.Response, err error) *WxaBindTesterResult { - return &WxaBindTesterResult{Result: result, Body: body, Http: http, Err: err} +func newWxaBindTesterResult(result WxaBindTesterResponse, body []byte, http gorequest.Response) *WxaBindTesterResult { + return &WxaBindTesterResult{Result: result, Body: body, Http: http} } // WxaBindTester 绑定微信用户为体验者 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Mini_Program_AdminManagement/Admin.html -func (c *Client) WxaBindTester(ctx context.Context, wechatid string) *WxaBindTesterResult { +func (c *Client) WxaBindTester(ctx context.Context, wechatid string) (*WxaBindTesterResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params["wechatid"] = wechatid // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/bind_tester?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaBindTesterResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaBindTesterResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaBindTesterResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.business.getuserphonenumber.go b/service/wechatopen/wxa.business.getuserphonenumber.go index b49db846..682d49f8 100644 --- a/service/wechatopen/wxa.business.getuserphonenumber.go +++ b/service/wechatopen/wxa.business.getuserphonenumber.go @@ -14,7 +14,7 @@ type WxaBusinessGetUserPhoneNumberResponse struct { PhoneInfo struct { PhoneNumber string `json:"phoneNumber"` // 用户绑定的手机号(国外手机号会有区号) PurePhoneNumber string `json:"purePhoneNumber"` // 没有区号的手机号 - CountryCode int `json:"countryCode"` // 区号 + CountryCode string `json:"countryCode"` // 区号 Watermark struct { Timestamp int `json:"timestamp"` // 用户获取手机号操作的时间戳 Appid string `json:"appid"` // 小程序appid @@ -26,25 +26,39 @@ type WxaBusinessGetUserPhoneNumberResult struct { Result WxaBusinessGetUserPhoneNumberResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaBusinessGetUserPhoneNumberResult(result WxaBusinessGetUserPhoneNumberResponse, body []byte, http gorequest.Response, err error) *WxaBusinessGetUserPhoneNumberResult { - return &WxaBusinessGetUserPhoneNumberResult{Result: result, Body: body, Http: http, Err: err} +func newWxaBusinessGetUserPhoneNumberResult(result WxaBusinessGetUserPhoneNumberResponse, body []byte, http gorequest.Response) *WxaBusinessGetUserPhoneNumberResult { + return &WxaBusinessGetUserPhoneNumberResult{Result: result, Body: body, Http: http} } // WxaBusinessGetUserPhoneNumber code换取用户手机号。 每个 code 只能使用一次,code的有效期为5min // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/phonenumber/phonenumber.getPhoneNumber.html -func (c *Client) WxaBusinessGetUserPhoneNumber(ctx context.Context, code string) *WxaBusinessGetUserPhoneNumberResult { +func (c *Client) WxaBusinessGetUserPhoneNumber(ctx context.Context, code string) (*WxaBusinessGetUserPhoneNumberResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params.Set("code", code) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/business/getuserphonenumber?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaBusinessGetUserPhoneNumberResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaBusinessGetUserPhoneNumberResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaBusinessGetUserPhoneNumberResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.commit.go b/service/wechatopen/wxa.commit.go index 44551be6..6dcedd4d 100644 --- a/service/wechatopen/wxa.commit.go +++ b/service/wechatopen/wxa.commit.go @@ -17,24 +17,38 @@ type WxaCommitResult struct { Result WxaCommitResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaCommitResult(result WxaCommitResponse, body []byte, http gorequest.Response, err error) *WxaCommitResult { - return &WxaCommitResult{Result: result, Body: body, Http: http, Err: err} +func newWxaCommitResult(result WxaCommitResponse, body []byte, http gorequest.Response) *WxaCommitResult { + return &WxaCommitResult{Result: result, Body: body, Http: http} } // WxaCommit 上传小程序代码并生成体验版 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/commit.html -func (c *Client) WxaCommit(ctx context.Context, notMustParams ...gorequest.Params) *WxaCommitResult { +func (c *Client) WxaCommit(ctx context.Context, notMustParams ...gorequest.Params) (*WxaCommitResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/commit?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaCommitResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaCommitResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaCommitResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.deletetemplate.go b/service/wechatopen/wxa.deletetemplate.go index 60114c16..ed3f1912 100644 --- a/service/wechatopen/wxa.deletetemplate.go +++ b/service/wechatopen/wxa.deletetemplate.go @@ -17,25 +17,35 @@ type WxaDeleteTemplateResult struct { Result WxaDeleteTemplateResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaDeleteTemplateResult(result WxaDeleteTemplateResponse, body []byte, http gorequest.Response, err error) *WxaDeleteTemplateResult { - return &WxaDeleteTemplateResult{Result: result, Body: body, Http: http, Err: err} +func newWxaDeleteTemplateResult(result WxaDeleteTemplateResponse, body []byte, http gorequest.Response) *WxaDeleteTemplateResult { + return &WxaDeleteTemplateResult{Result: result, Body: body, Http: http} } // WxaDeleteTemplate 删除指定代码模板 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/code_template/deletetemplate.html -func (c *Client) WxaDeleteTemplate(ctx context.Context, templateId string) *WxaDeleteTemplateResult { +func (c *Client) WxaDeleteTemplate(ctx context.Context, templateId string) (*WxaDeleteTemplateResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params.Set("template_id", templateId) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/deletetemplate?access_token=%s", c.GetComponentAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaDeleteTemplateResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaDeleteTemplateResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaDeleteTemplateResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.get_auditstatus.go b/service/wechatopen/wxa.get_auditstatus.go index f035d7cc..b078050e 100644 --- a/service/wechatopen/wxa.get_auditstatus.go +++ b/service/wechatopen/wxa.get_auditstatus.go @@ -21,25 +21,39 @@ type WxaGetAuditStatusResult struct { Result WxaGetAuditStatusResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetAuditStatusResult(result WxaGetAuditStatusResponse, body []byte, http gorequest.Response, err error) *WxaGetAuditStatusResult { - return &WxaGetAuditStatusResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetAuditStatusResult(result WxaGetAuditStatusResponse, body []byte, http gorequest.Response) *WxaGetAuditStatusResult { + return &WxaGetAuditStatusResult{Result: result, Body: body, Http: http} } // WxaGetAuditStatus 查询指定发布审核单的审核状态 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/get_auditstatus.html -func (c *Client) WxaGetAuditStatus(ctx context.Context, auditid int64) *WxaGetAuditStatusResult { +func (c *Client) WxaGetAuditStatus(ctx context.Context, auditid int64) (*WxaGetAuditStatusResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() params.Set("auditid", auditid) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_auditstatus?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaGetAuditStatusResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetAuditStatusResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetAuditStatusResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.get_category.go b/service/wechatopen/wxa.get_category.go index be360ce0..f8f9823e 100644 --- a/service/wechatopen/wxa.get_category.go +++ b/service/wechatopen/wxa.get_category.go @@ -25,20 +25,36 @@ type WxaGetCategoryResult struct { Result WxaGetCategoryResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetCategoryResult(result WxaGetCategoryResponse, body []byte, http gorequest.Response, err error) *WxaGetCategoryResult { - return &WxaGetCategoryResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetCategoryResult(result WxaGetCategoryResponse, body []byte, http gorequest.Response) *WxaGetCategoryResult { + return &WxaGetCategoryResult{Result: result, Body: body, Http: http} } // WxaGetCategory 获取审核时可填写的类目信息 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/category/get_category.html -func (c *Client) WxaGetCategory(ctx context.Context) *WxaGetCategoryResult { +func (c *Client) WxaGetCategory(ctx context.Context) (*WxaGetCategoryResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_category?access_token=%s", c.GetAuthorizerAccessToken(ctx)), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_category?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response WxaGetCategoryResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetCategoryResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetCategoryResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/wxa.get_effective_domain.go b/service/wechatopen/wxa.get_effective_domain.go index fa304d66..f061676f 100644 --- a/service/wechatopen/wxa.get_effective_domain.go +++ b/service/wechatopen/wxa.get_effective_domain.go @@ -41,22 +41,36 @@ type WxaGetEffectiveDomainResult struct { Result WxaGetEffectiveDomainResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetEffectiveDomainResult(result WxaGetEffectiveDomainResponse, body []byte, http gorequest.Response, err error) *WxaGetEffectiveDomainResult { - return &WxaGetEffectiveDomainResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetEffectiveDomainResult(result WxaGetEffectiveDomainResponse, body []byte, http gorequest.Response) *WxaGetEffectiveDomainResult { + return &WxaGetEffectiveDomainResult{Result: result, Body: body, Http: http} } // WxaGetEffectiveDomain 获取发布后生效服务器域名列表 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Mini_Program_Basic_Info/get_effective_domain.html -func (c *Client) WxaGetEffectiveDomain(ctx context.Context, notMustParams ...gorequest.Params) *WxaGetEffectiveDomainResult { +func (c *Client) WxaGetEffectiveDomain(ctx context.Context, notMustParams ...gorequest.Params) (*WxaGetEffectiveDomainResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_effective_domain?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaGetEffectiveDomainResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetEffectiveDomainResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetEffectiveDomainResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/wxa.get_effective_webviewdomain.go b/service/wechatopen/wxa.get_effective_webviewdomain.go new file mode 100644 index 00000000..bc17b569 --- /dev/null +++ b/service/wechatopen/wxa.get_effective_webviewdomain.go @@ -0,0 +1 @@ +package wechatopen diff --git a/service/wechatopen/wxa.get_latest_auditstatus.go b/service/wechatopen/wxa.get_latest_auditstatus.go index 3377e4c5..7fed332a 100644 --- a/service/wechatopen/wxa.get_latest_auditstatus.go +++ b/service/wechatopen/wxa.get_latest_auditstatus.go @@ -21,22 +21,38 @@ type WxaGetLatestAuditStatusResult struct { Result WxaGetLatestAuditStatusResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetLatestAuditStatusResult(result WxaGetLatestAuditStatusResponse, body []byte, http gorequest.Response, err error) *WxaGetLatestAuditStatusResult { - return &WxaGetLatestAuditStatusResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetLatestAuditStatusResult(result WxaGetLatestAuditStatusResponse, body []byte, http gorequest.Response) *WxaGetLatestAuditStatusResult { + return &WxaGetLatestAuditStatusResult{Result: result, Body: body, Http: http} } // WxaGetLatestAuditStatus 查询最新一次提交的审核状态 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/get_auditstatus.html -func (c *Client) WxaGetLatestAuditStatus(ctx context.Context) *WxaGetLatestAuditStatusResult { +func (c *Client) WxaGetLatestAuditStatus(ctx context.Context) (*WxaGetLatestAuditStatusResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_latest_auditstatus?access_token=%s", c.GetAuthorizerAccessToken(ctx)), map[string]interface{}{}, http.MethodPost) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_latest_auditstatus?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaGetLatestAuditStatusResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetLatestAuditStatusResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetLatestAuditStatusResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.get_page.go b/service/wechatopen/wxa.get_page.go index 369f0fe5..a65d59bc 100644 --- a/service/wechatopen/wxa.get_page.go +++ b/service/wechatopen/wxa.get_page.go @@ -18,20 +18,36 @@ type WxaGetPageResult struct { Result WxaGetPageResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetPageResult(result WxaGetPageResponse, body []byte, http gorequest.Response, err error) *WxaGetPageResult { - return &WxaGetPageResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetPageResult(result WxaGetPageResponse, body []byte, http gorequest.Response) *WxaGetPageResult { + return &WxaGetPageResult{Result: result, Body: body, Http: http} } // WxaGetPage 获取已上传的代码的页面列表 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/get_page.html -func (c *Client) WxaGetPage(ctx context.Context) *WxaGetPageResult { +func (c *Client) WxaGetPage(ctx context.Context) (*WxaGetPageResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_page?access_token=%s", c.GetAuthorizerAccessToken(ctx)), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_page?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response WxaGetPageResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetPageResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetPageResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/wxa.get_prefetchdnsdomai.go b/service/wechatopen/wxa.get_prefetchdnsdomai.go new file mode 100644 index 00000000..bc17b569 --- /dev/null +++ b/service/wechatopen/wxa.get_prefetchdnsdomai.go @@ -0,0 +1 @@ +package wechatopen diff --git a/service/wechatopen/wxa.get_qrcode.go b/service/wechatopen/wxa.get_qrcode.go index 6228b9c7..23d45307 100644 --- a/service/wechatopen/wxa.get_qrcode.go +++ b/service/wechatopen/wxa.get_qrcode.go @@ -1,10 +1,12 @@ package wechatopen import ( + "bytes" "context" "encoding/json" "fmt" "github.com/dtapps/go-library/utils/gorequest" + "github.com/dtapps/go-library/utils/gostorage" "net/http" ) @@ -17,16 +19,24 @@ type WxaGetQrcodeResult struct { Result WxaGetQrcodeResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetQrcodeResult(result WxaGetQrcodeResponse, body []byte, http gorequest.Response, err error) *WxaGetQrcodeResult { - return &WxaGetQrcodeResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetQrcodeResult(result WxaGetQrcodeResponse, body []byte, http gorequest.Response) *WxaGetQrcodeResult { + return &WxaGetQrcodeResult{Result: result, Body: body, Http: http} } // WxaGetQrcode 获取体验版二维码 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/get_qrcode.html -func (c *Client) WxaGetQrcode(ctx context.Context, path string) *WxaGetQrcodeResult { +func (c *Client) WxaGetQrcode(ctx context.Context, path string) (*WxaGetQrcodeResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() if path != "" { @@ -34,8 +44,30 @@ func (c *Client) WxaGetQrcode(ctx context.Context, path string) *WxaGetQrcodeRes } // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/get_qrcode?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response WxaGetQrcodeResponse - err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetQrcodeResult(response, request.ResponseBody, request, err) + // 判断内容是否为图片 + if request.HeaderIsImg() { + } else { + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + } + return newWxaGetQrcodeResult(response, request.ResponseBody, request), nil +} + +func (cr *WxaGetQrcodeResult) SaveImg(db *gostorage.AliYun, fileName, filePath string) error { + if cr.Result.Errcode != 0 { + panic(fmt.Sprintf("接口状态错误:%s", cr.Body)) + } + // 上传 + _, err := db.PutObject(bytes.NewReader(cr.Body), filePath, fileName) + if err != nil { + return err + } + return nil } diff --git a/service/wechatopen/wxa.get_webviewdomain_confirmfile.go b/service/wechatopen/wxa.get_webviewdomain_confirmfile.go new file mode 100644 index 00000000..bc17b569 --- /dev/null +++ b/service/wechatopen/wxa.get_webviewdomain_confirmfile.go @@ -0,0 +1 @@ +package wechatopen diff --git a/service/wechatopen/wxa.gettemplatedraftlist.go b/service/wechatopen/wxa.gettemplatedraftlist.go index 8cb56ad1..b5a8e42d 100644 --- a/service/wechatopen/wxa.gettemplatedraftlist.go +++ b/service/wechatopen/wxa.gettemplatedraftlist.go @@ -27,22 +27,34 @@ type WxaGetTemplateDraftListResult struct { Result WxaGetTemplateDraftListResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetTemplateDraftListResult(result WxaGetTemplateDraftListResponse, body []byte, http gorequest.Response, err error) *WxaGetTemplateDraftListResult { - return &WxaGetTemplateDraftListResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetTemplateDraftListResult(result WxaGetTemplateDraftListResponse, body []byte, http gorequest.Response) *WxaGetTemplateDraftListResult { + return &WxaGetTemplateDraftListResult{Result: result, Body: body, Http: http} } // WxaGetTemplateDraftList 获取代码草稿列表 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/code_template/gettemplatedraftlist.html -func (c *Client) WxaGetTemplateDraftList(ctx context.Context) *WxaGetTemplateDraftListResult { +func (c *Client) WxaGetTemplateDraftList(ctx context.Context) (*WxaGetTemplateDraftListResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/gettemplatedraftlist?access_token=%s", c.GetComponentAccessToken(ctx)), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/gettemplatedraftlist?access_token=%s", c.GetComponentAccessToken(ctx)), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response WxaGetTemplateDraftListResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetTemplateDraftListResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetTemplateDraftListResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.gettemplatelist.go b/service/wechatopen/wxa.gettemplatelist.go index 66b31864..8960a43b 100644 --- a/service/wechatopen/wxa.gettemplatelist.go +++ b/service/wechatopen/wxa.gettemplatelist.go @@ -28,22 +28,34 @@ type WxaGetTemplateListResult struct { Result WxaGetTemplateListResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetTemplateListResult(result WxaGetTemplateListResponse, body []byte, http gorequest.Response, err error) *WxaGetTemplateListResult { - return &WxaGetTemplateListResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetTemplateListResult(result WxaGetTemplateListResponse, body []byte, http gorequest.Response) *WxaGetTemplateListResult { + return &WxaGetTemplateListResult{Result: result, Body: body, Http: http} } // WxaGetTemplateList 获取代码模板列表 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/ThirdParty/code_template/gettemplatelist.html -func (c *Client) WxaGetTemplateList(ctx context.Context) *WxaGetTemplateListResult { +func (c *Client) WxaGetTemplateList(ctx context.Context) (*WxaGetTemplateListResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/gettemplatelist?access_token=%s", c.GetComponentAccessToken(ctx)), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/gettemplatelist?access_token=%s", c.GetComponentAccessToken(ctx)), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response WxaGetTemplateListResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetTemplateListResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetTemplateListResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.getversioninfo.go b/service/wechatopen/wxa.getversioninfo.go index 968d93ac..72e2176f 100644 --- a/service/wechatopen/wxa.getversioninfo.go +++ b/service/wechatopen/wxa.getversioninfo.go @@ -3,7 +3,6 @@ package wechatopen import ( "context" "encoding/json" - "errors" "fmt" "github.com/dtapps/go-library/utils/gorequest" "net/http" @@ -28,24 +27,36 @@ type WxaGetVersionInfoResult struct { Result WxaGetVersionInfoResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetVersionInfoResult(result WxaGetVersionInfoResponse, body []byte, http gorequest.Response, err error) *WxaGetVersionInfoResult { - return &WxaGetVersionInfoResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetVersionInfoResult(result WxaGetVersionInfoResponse, body []byte, http gorequest.Response) *WxaGetVersionInfoResult { + return &WxaGetVersionInfoResult{Result: result, Body: body, Http: http} } // WxaGetVersionInfo 查询小程序版本信息 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/get_versioninfo.html -func (c *Client) WxaGetVersionInfo(ctx context.Context) *WxaGetVersionInfoResult { - accessToken := c.GetAuthorizerAccessToken(ctx) - if accessToken == "" { - return newWxaGetVersionInfoResult(WxaGetVersionInfoResponse{}, nil, gorequest.Response{}, errors.New("访问令牌为空")) +func (c *Client) WxaGetVersionInfo(ctx context.Context) (*WxaGetVersionInfoResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/getversioninfo?access_token=%s", accessToken), map[string]interface{}{}, http.MethodPost) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/getversioninfo?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaGetVersionInfoResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetVersionInfoResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaGetVersionInfoResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/wxa.getwxacodeunlimit.go b/service/wechatopen/wxa.getwxacodeunlimit.go index 28e39235..d6707d46 100644 --- a/service/wechatopen/wxa.getwxacodeunlimit.go +++ b/service/wechatopen/wxa.getwxacodeunlimit.go @@ -19,24 +19,42 @@ type WxaGetWxaCodeUnLimitResult struct { Result WxaGetWxaCodeUnLimitResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaGetWxaCodeUnLimitResult(result WxaGetWxaCodeUnLimitResponse, body []byte, http gorequest.Response, err error) *WxaGetWxaCodeUnLimitResult { - return &WxaGetWxaCodeUnLimitResult{Result: result, Body: body, Http: http, Err: err} +func newWxaGetWxaCodeUnLimitResult(result WxaGetWxaCodeUnLimitResponse, body []byte, http gorequest.Response) *WxaGetWxaCodeUnLimitResult { + return &WxaGetWxaCodeUnLimitResult{Result: result, Body: body, Http: http} } // WxaGetWxaCodeUnLimit 获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制 // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html -func (c *Client) WxaGetWxaCodeUnLimit(ctx context.Context, notMustParams ...gorequest.Params) *WxaGetWxaCodeUnLimitResult { +func (c *Client) WxaGetWxaCodeUnLimit(ctx context.Context, notMustParams ...gorequest.Params) (*WxaGetWxaCodeUnLimitResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/getwxacodeunlimit?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaGetWxaCodeUnLimitResponse - err = json.Unmarshal(request.ResponseBody, &response) - return newWxaGetWxaCodeUnLimitResult(response, request.ResponseBody, request, err) + // 判断内容是否为图片 + if request.HeaderIsImg() { + } else { + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + } + return newWxaGetWxaCodeUnLimitResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.memberauth.go b/service/wechatopen/wxa.memberauth.go index fea95ca9..2c54dd32 100644 --- a/service/wechatopen/wxa.memberauth.go +++ b/service/wechatopen/wxa.memberauth.go @@ -3,7 +3,6 @@ package wechatopen import ( "context" "encoding/json" - "errors" "fmt" "github.com/dtapps/go-library/utils/gorequest" "net/http" @@ -21,27 +20,37 @@ type WxaMemberAuthResult struct { Result WxaMemberAuthResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaMemberAuthResult(result WxaMemberAuthResponse, body []byte, http gorequest.Response, err error) *WxaMemberAuthResult { - return &WxaMemberAuthResult{Result: result, Body: body, Http: http, Err: err} +func newWxaMemberAuthResult(result WxaMemberAuthResponse, body []byte, http gorequest.Response) *WxaMemberAuthResult { + return &WxaMemberAuthResult{Result: result, Body: body, Http: http} } // WxaMemberAuth 获取体验者列表 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Mini_Program_AdminManagement/memberauth.html -func (c *Client) WxaMemberAuth(ctx context.Context) *WxaMemberAuthResult { - accessToken := c.GetAuthorizerAccessToken(ctx) - if accessToken == "" { - return newWxaMemberAuthResult(WxaMemberAuthResponse{}, nil, gorequest.Response{}, errors.New("访问令牌为空")) +func (c *Client) WxaMemberAuth(ctx context.Context) (*WxaMemberAuthResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err } // 参数 params := gorequest.NewParams() params["action"] = "get_experiencer" // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/memberauth?access_token=%s", accessToken), params, http.MethodPost) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/memberauth?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaMemberAuthResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaMemberAuthResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaMemberAuthResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/wxa.modify_domain.go b/service/wechatopen/wxa.modify_domain.go index 042bf395..f036cf78 100644 --- a/service/wechatopen/wxa.modify_domain.go +++ b/service/wechatopen/wxa.modify_domain.go @@ -30,24 +30,34 @@ type WxaModifyDomainResult struct { Result WxaModifyDomainResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaModifyDomainResult(result WxaModifyDomainResponse, body []byte, http gorequest.Response, err error) *WxaModifyDomainResult { - return &WxaModifyDomainResult{Result: result, Body: body, Http: http, Err: err} +func newWxaModifyDomainResult(result WxaModifyDomainResponse, body []byte, http gorequest.Response) *WxaModifyDomainResult { + return &WxaModifyDomainResult{Result: result, Body: body, Http: http} } -// WxaModifyDomain 设置服务器域名 -// https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Mini_Program_Basic_Info/Server_Address_Configuration.html -func (c *Client) WxaModifyDomain(ctx context.Context, notMustParams ...gorequest.Params) *WxaModifyDomainResult { +// WxaModifyDomain 配置小程序服务器域名 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/domain-management/modifyServerDomain.html +func (c *Client) WxaModifyDomain(ctx context.Context, notMustParams ...gorequest.Params) (*WxaModifyDomainResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/modify_domain?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaModifyDomainResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaModifyDomainResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaModifyDomainResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.modify_domain_directly.go b/service/wechatopen/wxa.modify_domain_directly.go index 86e429e6..6618f89e 100644 --- a/service/wechatopen/wxa.modify_domain_directly.go +++ b/service/wechatopen/wxa.modify_domain_directly.go @@ -9,32 +9,55 @@ import ( ) type WxaModifyDomainDirectlyResponse struct { - Errcode int `json:"errcode"` // 错误码 - Errmsg string `json:"errmsg"` // 错误信息 + Errcode int `json:"errcode"` // 错误码 + Errmsg string `json:"errmsg"` // 错误信息 + Requestdomain []string `json:"requestdomain"` // request 合法域名 + Wsrequestdomain []string `json:"wsrequestdomain"` // socket 合法域名 + Uploaddomain []string `json:"uploaddomain"` // uploadFile 合法域名 + Downloaddomain []string `json:"downloaddomain"` // downloadFile 合法域名 + Udpdomain []string `json:"udpdomain"` // udp 合法域名 + Tcpdomain []string `json:"tcpdomain"` // tcp 合法域名 + InvalidRequestdomain []string `json:"invalid_requestdomain"` // request 不合法域名 + InvalidWsrequestdomain []string `json:"invalid_wsrequestdomain"` // socket 不合法域名 + InvalidUploaddomain []string `json:"invalid_uploaddomain"` // uploadFile 不合法域名 + InvalidDownloaddomain []string `json:"invalid_downloaddomain"` // downloadFile 不合法域名 + InvalidUdpdomain []string `json:"invalid_udpdomain"` // udp 不合法域名 + InvalidTcpdomain []string `json:"invalid_tcpdomain"` // tcp 不合法域名 + NoIcpDomain []string `json:"no_icp_domain"` // 没有经过icp备案的域名 } type WxaModifyDomainDirectlyResult struct { Result WxaModifyDomainDirectlyResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaModifyDomainDirectlyResult(result WxaModifyDomainDirectlyResponse, body []byte, http gorequest.Response, err error) *WxaModifyDomainDirectlyResult { - return &WxaModifyDomainDirectlyResult{Result: result, Body: body, Http: http, Err: err} +func newWxaModifyDomainDirectlyResult(result WxaModifyDomainDirectlyResponse, body []byte, http gorequest.Response) *WxaModifyDomainDirectlyResult { + return &WxaModifyDomainDirectlyResult{Result: result, Body: body, Http: http} } -// WxaModifyDomainDirectly 快速设置小程序服务器域名 -// https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Mini_Program_Basic_Info/modify_domain_directly.html -func (c *Client) WxaModifyDomainDirectly(ctx context.Context, notMustParams ...gorequest.Params) *WxaModifyDomainDirectlyResult { +// WxaModifyDomainDirectly 快速配置小程序服务器域名 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/domain-management/modifyServerDomainDirectly.html +func (c *Client) WxaModifyDomainDirectly(ctx context.Context, notMustParams ...gorequest.Params) (*WxaModifyDomainDirectlyResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/modify_domain_directly?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaModifyDomainDirectlyResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaModifyDomainDirectlyResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaModifyDomainDirectlyResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.release.go b/service/wechatopen/wxa.release.go index c571f05b..8f537136 100644 --- a/service/wechatopen/wxa.release.go +++ b/service/wechatopen/wxa.release.go @@ -17,24 +17,38 @@ type WxaReleaseResult struct { Result WxaReleaseResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaReleaseResult(result WxaReleaseResponse, body []byte, http gorequest.Response, err error) *WxaReleaseResult { - return &WxaReleaseResult{Result: result, Body: body, Http: http, Err: err} +func newWxaReleaseResult(result WxaReleaseResponse, body []byte, http gorequest.Response) *WxaReleaseResult { + return &WxaReleaseResult{Result: result, Body: body, Http: http} } // WxaRelease 发布已通过审核的小程序 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/release.html -func (c *Client) WxaRelease(ctx context.Context) *WxaReleaseResult { +func (c *Client) WxaRelease(ctx context.Context) (*WxaReleaseResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + err = c.checkAuthorizerIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/release?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaReleaseResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaReleaseResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaReleaseResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.security.apply_privacy_interface.go b/service/wechatopen/wxa.security.apply_privacy_interface.go index 48c65354..17905f34 100644 --- a/service/wechatopen/wxa.security.apply_privacy_interface.go +++ b/service/wechatopen/wxa.security.apply_privacy_interface.go @@ -18,24 +18,34 @@ type WxaSecurityApplyPrivacyInterfaceResult struct { Result WxaSecurityApplyPrivacyInterfaceResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaSecurityApplyPrivacyInterfaceResult(result WxaSecurityApplyPrivacyInterfaceResponse, body []byte, http gorequest.Response, err error) *WxaSecurityApplyPrivacyInterfaceResult { - return &WxaSecurityApplyPrivacyInterfaceResult{Result: result, Body: body, Http: http, Err: err} +func newWxaSecurityApplyPrivacyInterfaceResult(result WxaSecurityApplyPrivacyInterfaceResponse, body []byte, http gorequest.Response) *WxaSecurityApplyPrivacyInterfaceResult { + return &WxaSecurityApplyPrivacyInterfaceResult{Result: result, Body: body, Http: http} } // WxaSecurityApplyPrivacyInterface 申请接口 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/apply_api/apply_privacy_interface.html -func (c *Client) WxaSecurityApplyPrivacyInterface(ctx context.Context, notMustParams ...gorequest.Params) *WxaSecurityApplyPrivacyInterfaceResult { +func (c *Client) WxaSecurityApplyPrivacyInterface(ctx context.Context, notMustParams ...gorequest.Params) (*WxaSecurityApplyPrivacyInterfaceResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/security/apply_privacy_interface?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaSecurityApplyPrivacyInterfaceResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaSecurityApplyPrivacyInterfaceResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaSecurityApplyPrivacyInterfaceResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.security.applysetorderpathinfo.go b/service/wechatopen/wxa.security.applysetorderpathinfo.go new file mode 100644 index 00000000..c7eafc01 --- /dev/null +++ b/service/wechatopen/wxa.security.applysetorderpathinfo.go @@ -0,0 +1,61 @@ +package wechatopen + +import ( + "context" + "encoding/json" + "fmt" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type WxaSecurityApplySetOrderPathInfoResponse struct { + Errcode int `json:"errcode"` // 返回码 + Errmsg string `json:"errmsg"` // 返回码信息 +} + +type WxaSecurityApplySetOrderPathInfoResult struct { + Result WxaSecurityApplySetOrderPathInfoResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 +} + +func newWxaSecurityApplySetOrderPathInfoResult(result WxaSecurityApplySetOrderPathInfoResponse, body []byte, http gorequest.Response) *WxaSecurityApplySetOrderPathInfoResult { + return &WxaSecurityApplySetOrderPathInfoResult{Result: result, Body: body, Http: http} +} + +// WxaSecurityApplySetOrderPathInfo 申请设置订单页 path 信息 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/basic-info-management/applySetOrderPathInfo.html +func (c *Client) WxaSecurityApplySetOrderPathInfo(ctx context.Context, notMustParams ...gorequest.Params) (*WxaSecurityApplySetOrderPathInfoResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + // 请求 + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/security/applysetorderpathinfo?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } + // 定义 + var response WxaSecurityApplySetOrderPathInfoResponse + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + return newWxaSecurityApplySetOrderPathInfoResult(response, request.ResponseBody, request), nil +} + +// ErrcodeInfo 错误描述 +func (resp *WxaSecurityApplySetOrderPathInfoResult) ErrcodeInfo() string { + switch resp.Result.Errcode { + case 61042: + return "批量提交超过最大数量,一次提交的 appid 数量不超过100个" + case 61043: + return "参数填写错误" + case 61044: + return "path填写不规范" + } + return "系统繁忙" +} diff --git a/service/wechatopen/wxa.security.get_privacy_interface.go b/service/wechatopen/wxa.security.get_privacy_interface.go index 389fd31f..fb3828f0 100644 --- a/service/wechatopen/wxa.security.get_privacy_interface.go +++ b/service/wechatopen/wxa.security.get_privacy_interface.go @@ -16,7 +16,7 @@ type WxaSecurityGetPrivacyInterfaceResponse struct { ApiChName string `json:"api_ch_name"` // api 中文名 ApiDesc string `json:"api_desc"` // api描述 ApplyTime int64 `json:"apply_time,omitempty"` // 申请时间 ,该字段发起申请后才会有 - Status int `json:"status"` // 接口状态,该字段发起申请后才会有 + Status int `json:"status,omitempty"` // 接口状态,该字段发起申请后才会有 1待申请开通 2无权限 3申请中 4申请失败 5已开通 AuditId int `json:"audit_id,omitempty"` // 申请单号,该字段发起申请后才会有 FailReason string `json:"fail_reason,omitempty"` // 申请被驳回原因或者无权限,该字段申请驳回时才会有 ApiLink string `json:"api_link"` // api文档链接 @@ -28,24 +28,34 @@ type WxaSecurityGetPrivacyInterfaceResult struct { Result WxaSecurityGetPrivacyInterfaceResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaSecurityGetPrivacyInterfaceResult(result WxaSecurityGetPrivacyInterfaceResponse, body []byte, http gorequest.Response, err error) *WxaSecurityGetPrivacyInterfaceResult { - return &WxaSecurityGetPrivacyInterfaceResult{Result: result, Body: body, Http: http, Err: err} +func newWxaSecurityGetPrivacyInterfaceResult(result WxaSecurityGetPrivacyInterfaceResponse, body []byte, http gorequest.Response) *WxaSecurityGetPrivacyInterfaceResult { + return &WxaSecurityGetPrivacyInterfaceResult{Result: result, Body: body, Http: http} } // WxaSecurityGetPrivacyInterface 获取接口列表 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/apply_api/get_privacy_interface.html -func (c *Client) WxaSecurityGetPrivacyInterface(ctx context.Context) *WxaSecurityGetPrivacyInterfaceResult { +func (c *Client) WxaSecurityGetPrivacyInterface(ctx context.Context) (*WxaSecurityGetPrivacyInterfaceResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/security/get_privacy_interface?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodGet) + if err != nil { + return nil, err + } // 定义 var response WxaSecurityGetPrivacyInterfaceResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaSecurityGetPrivacyInterfaceResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaSecurityGetPrivacyInterfaceResult(response, request.ResponseBody, request), nil } // ErrcodeInfo 错误描述 diff --git a/service/wechatopen/wxa.security.getorderpathinfo.go b/service/wechatopen/wxa.security.getorderpathinfo.go new file mode 100644 index 00000000..8f8dc52a --- /dev/null +++ b/service/wechatopen/wxa.security.getorderpathinfo.go @@ -0,0 +1,68 @@ +package wechatopen + +import ( + "context" + "encoding/json" + "fmt" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type WxaSecurityGetOrderPathInfoResponse struct { + Errcode int `json:"errcode"` // 返回码 + Errmsg string `json:"errmsg"` // 返回码信息 + msg struct { + Path string `json:"path"` + ImgList []string `json:"img_list"` + Video string `json:"video"` + TestAccount string `json:"test_account"` + TestPwd string `json:"test_pwd"` + TestRemark string `json:"test_remark"` + Status int `json:"status"` + ApplyTime int64 `json:"apply_time"` + } `json:"msg"` +} + +type WxaSecurityGetOrderPathInfoResult struct { + Result WxaSecurityGetOrderPathInfoResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 +} + +func newWxaSecurityGetOrderPathInfoResult(result WxaSecurityGetOrderPathInfoResponse, body []byte, http gorequest.Response) *WxaSecurityGetOrderPathInfoResult { + return &WxaSecurityGetOrderPathInfoResult{Result: result, Body: body, Http: http} +} + +// WxaSecurityGetOrderPathInfo 获取订单页 path 信息 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/basic-info-management/getOrderPathInfo.html +func (c *Client) WxaSecurityGetOrderPathInfo(ctx context.Context, infoType int) (*WxaSecurityGetOrderPathInfoResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParams() + params.Set("info_type", infoType) + // 请求 + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/security/getorderpathinfo?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } + // 定义 + var response WxaSecurityGetOrderPathInfoResponse + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + return newWxaSecurityGetOrderPathInfoResult(response, request.ResponseBody, request), nil +} + +// ErrcodeInfo 错误描述 +func (resp *WxaSecurityGetOrderPathInfoResult) ErrcodeInfo() string { + switch resp.Result.Errcode { + case 61041: + return "订单页 path 未设置" + } + return "系统繁忙" +} diff --git a/service/wechatopen/wxa.set_prefetchdnsdomain.go b/service/wechatopen/wxa.set_prefetchdnsdomain.go new file mode 100644 index 00000000..bc17b569 --- /dev/null +++ b/service/wechatopen/wxa.set_prefetchdnsdomain.go @@ -0,0 +1 @@ +package wechatopen diff --git a/service/wechatopen/wxa.setwebviewdomain.go b/service/wechatopen/wxa.setwebviewdomain.go new file mode 100644 index 00000000..8ab72bb5 --- /dev/null +++ b/service/wechatopen/wxa.setwebviewdomain.go @@ -0,0 +1,67 @@ +package wechatopen + +import ( + "context" + "encoding/json" + "fmt" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type WxaSetWebViewDoMainResponse struct { + Errcode int `json:"errcode"` // 错误码 + Errmsg string `json:"errmsg"` // 错误信息 +} + +type WxaSetWebViewDoMainResult struct { + Result WxaSetWebViewDoMainResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 +} + +func newWxaSetWebViewDoMainResult(result WxaSetWebViewDoMainResponse, body []byte, http gorequest.Response) *WxaSetWebViewDoMainResult { + return &WxaSetWebViewDoMainResult{Result: result, Body: body, Http: http} +} + +// WxaSetWebViewDoMain 配置小程序业务域名 +// https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/domain-management/modifyJumpDomain.html +func (c *Client) WxaSetWebViewDoMain(ctx context.Context, notMustParams ...gorequest.Params) (*WxaSetWebViewDoMainResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + // 请求 + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/setwebviewdomain?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } + // 定义 + var response WxaSetWebViewDoMainResponse + err = json.Unmarshal(request.ResponseBody, &response) + if err != nil { + return nil, err + } + return newWxaSetWebViewDoMainResult(response, request.ResponseBody, request), nil +} + +// ErrcodeInfo 错误描述 +func (resp *WxaSetWebViewDoMainResult) ErrcodeInfo() string { + switch resp.Result.Errcode { + case 40001: + return "获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口" + case 89019: + return "业务域名无更改,无需重复设置" + case 89020: + return "尚未设置小程序业务域名,请先在第三方平台中设置小程序业务域名后在调用本接口" + case 89021: + return "请求保存的域名不是第三方平台中已设置的小程序业务域名或子域名" + case 89029: + return "业务域名数量超过限制,最多可以添加100个业务域名" + case 89231: + return "个人小程序不支持调用 setwebviewdomain 接口" + } + return "系统繁忙" +} diff --git a/service/wechatopen/wxa.setwebviewdomain_directly.go b/service/wechatopen/wxa.setwebviewdomain_directly.go new file mode 100644 index 00000000..bc17b569 --- /dev/null +++ b/service/wechatopen/wxa.setwebviewdomain_directly.go @@ -0,0 +1 @@ +package wechatopen diff --git a/service/wechatopen/wxa.submit_audit.go b/service/wechatopen/wxa.submit_audit.go index 5795e992..4037e18b 100644 --- a/service/wechatopen/wxa.submit_audit.go +++ b/service/wechatopen/wxa.submit_audit.go @@ -18,22 +18,32 @@ type WxaSubmitAuditResult struct { Result WxaSubmitAuditResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaSubmitAuditResult(result WxaSubmitAuditResponse, body []byte, http gorequest.Response, err error) *WxaSubmitAuditResult { - return &WxaSubmitAuditResult{Result: result, Body: body, Http: http, Err: err} +func newWxaSubmitAuditResult(result WxaSubmitAuditResponse, body []byte, http gorequest.Response) *WxaSubmitAuditResult { + return &WxaSubmitAuditResult{Result: result, Body: body, Http: http} } // WxaSubmitAudit 提交审核 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/submit_audit.html -func (c *Client) WxaSubmitAudit(ctx context.Context, notMustParams ...gorequest.Params) *WxaSubmitAuditResult { +func (c *Client) WxaSubmitAudit(ctx context.Context, notMustParams ...gorequest.Params) (*WxaSubmitAuditResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParamsWith(notMustParams...) // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/submit_audit?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaSubmitAuditResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaSubmitAuditResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaSubmitAuditResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatopen/wxa.unbind_tester.go b/service/wechatopen/wxa.unbind_tester.go index 4413b628..d9648997 100644 --- a/service/wechatopen/wxa.unbind_tester.go +++ b/service/wechatopen/wxa.unbind_tester.go @@ -17,16 +17,20 @@ type WxaUnbindTesterResult struct { Result WxaUnbindTesterResponse // 结果 Body []byte // 内容 Http gorequest.Response // 请求 - Err error // 错误 } -func newWxaUnbindTesterResult(result WxaUnbindTesterResponse, body []byte, http gorequest.Response, err error) *WxaUnbindTesterResult { - return &WxaUnbindTesterResult{Result: result, Body: body, Http: http, Err: err} +func newWxaUnbindTesterResult(result WxaUnbindTesterResponse, body []byte, http gorequest.Response) *WxaUnbindTesterResult { + return &WxaUnbindTesterResult{Result: result, Body: body, Http: http} } // WxaUnbindTester 解除绑定体验者 // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Mini_Program_AdminManagement/unbind_tester.html -func (c *Client) WxaUnbindTester(ctx context.Context, wechatid, userstr string) *WxaUnbindTesterResult { +func (c *Client) WxaUnbindTester(ctx context.Context, wechatid, userstr string) (*WxaUnbindTesterResult, error) { + // 检查 + err := c.checkComponentIsConfig() + if err != nil { + return nil, err + } // 参数 params := gorequest.NewParams() if wechatid != "" { @@ -35,8 +39,14 @@ func (c *Client) WxaUnbindTester(ctx context.Context, wechatid, userstr string) params["userstr"] = userstr // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/wxa/unbind_tester?access_token=%s", c.GetAuthorizerAccessToken(ctx)), params, http.MethodPost) + if err != nil { + return nil, err + } // 定义 var response WxaUnbindTesterResponse err = json.Unmarshal(request.ResponseBody, &response) - return newWxaUnbindTesterResult(response, request.ResponseBody, request, err) + if err != nil { + return nil, err + } + return newWxaUnbindTesterResult(response, request.ResponseBody, request), nil } diff --git a/service/wechatpayapiv2/client.go b/service/wechatpayapiv2/client.go index 2f169d99..97703b8c 100644 --- a/service/wechatpayapiv2/client.go +++ b/service/wechatpayapiv2/client.go @@ -1,57 +1,50 @@ package wechatpayapiv2 import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppId string // 小程序或者公众号唯一凭证 - AppSecret string // 小程序或者公众号唯一凭证密钥 - MchId string // 微信支付的商户id - MchKey string // 私钥 - CertString string - KeyString string - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string // 小程序或者公众号唯一凭证 + AppSecret string // 小程序或者公众号唯一凭证密钥 + MchId string // 微信支付的商户id + MchKey string // 私钥 + CertString string + KeyString string } -// Client 微信支付服务 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appId string // 小程序或者公众号唯一凭证 + appSecret string // 小程序或者公众号唯一凭证密钥 + mchId string // 微信支付的商户id + mchKey string // 私钥 + certString string + keyString string + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appId = config.AppId + c.config.appSecret = config.AppSecret + c.config.mchId = config.MchId + c.config.mchKey = config.MchKey + c.config.certString = config.CertString + c.config.keyString = config.KeyString - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/wechatpayapiv2/config.go b/service/wechatpayapiv2/config.go new file mode 100644 index 00000000..47270fb7 --- /dev/null +++ b/service/wechatpayapiv2/config.go @@ -0,0 +1,12 @@ +package wechatpayapiv2 + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatpayapiv2/const.go b/service/wechatpayapiv2/const.go index a45d8d6e..bb6c109e 100644 --- a/service/wechatpayapiv2/const.go +++ b/service/wechatpayapiv2/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "wechatpayapiv2" + LogTable = "wechatpayapiv2" ) diff --git a/service/wechatpayapiv2/get.go b/service/wechatpayapiv2/get.go index 01b2595c..37035b42 100644 --- a/service/wechatpayapiv2/get.go +++ b/service/wechatpayapiv2/get.go @@ -1,28 +1,39 @@ package wechatpayapiv2 -import "crypto/tls" +import ( + "crypto/tls" + "github.com/dtapps/go-library/utils/golog" +) func (c *Client) GetAppId() string { - return c.config.AppId + return c.config.appId +} + +func (c *Client) GetAppSecret() string { + return c.config.appSecret } func (c *Client) GetMchId() string { - return c.config.MchId + return c.config.mchId } func (c *Client) GetMchKey() string { - return c.config.MchKey + return c.config.mchKey } func (c *Client) GetCertString() string { - return c.config.CertString + return c.config.certString } func (c *Client) GetKeyString() string { - return c.config.KeyString + return c.config.keyString } func (c *Client) P12ToPem() (*tls.Certificate, error) { pemCert, err := tls.X509KeyPair([]byte(c.GetCertString()), []byte(c.GetKeyString())) return &pemCert, err } + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/wechatpayapiv2/mmpaymkttransfers.gettransferinfo.go b/service/wechatpayapiv2/mmpaymkttransfers.gettransferinfo.go index 545d64fe..60d1906f 100644 --- a/service/wechatpayapiv2/mmpaymkttransfers.gettransferinfo.go +++ b/service/wechatpayapiv2/mmpaymkttransfers.gettransferinfo.go @@ -8,11 +8,13 @@ import ( ) type TransfersQueryResponse struct { - ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 - ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 - ResultCode string `json:"result_code" xml:"result_code"` // 业务结果 - ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 - ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 + ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 + + ResultCode string `json:"result_code" xml:"result_code"` // 业务结果 + ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 + ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + PartnerTradeNo string `json:"partner_trade_no" xml:"partner_trade_no"` // 商户单号 Appid string `json:"appid" xml:"appid"` // Appid MchId string `json:"mch_id" xml:"mch_id"` // 商户号 @@ -40,6 +42,7 @@ func newTransfersQueryResult(result TransfersQueryResponse, body []byte, http go // TransfersQuery // 付款到零钱 - 查询付款 +// 需要证书 // https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3 func (c *Client) TransfersQuery(ctx context.Context, partnerTradeNo string) *TransfersQueryResult { cert, err := c.P12ToPem() @@ -52,7 +55,7 @@ func (c *Client) TransfersQuery(ctx context.Context, partnerTradeNo string) *Tra // 签名 params.Set("sign", c.getMd5Sign(params)) // 请求 - request, err := c.request(ctx, apiUrl+"/mmpaymkttransfers/gettransferinfo", params, cert) + request, err := c.request(ctx, apiUrl+"/mmpaymkttransfers/gettransferinfo", params, true, cert) // 定义 var response TransfersQueryResponse err = xml.Unmarshal(request.ResponseBody, &response) diff --git a/service/wechatpayapiv2/mmpaymkttransfers.promotion.transfers.go b/service/wechatpayapiv2/mmpaymkttransfers.promotion.transfers.go index 6bb05231..4d59fb3e 100644 --- a/service/wechatpayapiv2/mmpaymkttransfers.promotion.transfers.go +++ b/service/wechatpayapiv2/mmpaymkttransfers.promotion.transfers.go @@ -8,18 +8,20 @@ import ( ) type TransfersResponse struct { - ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 - ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 - MchAppid string `json:"mch_appid" xml:"mch_appid"` // 商户appid - Mchid string `json:"mchid" xml:"mchid"` // 商户号 - DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"` // 设备号 - NonceStr string `json:"nonce_str" xml:"nonce_str"` // 随机字符串 - ResultCode string `json:"result_code" xml:"result_code"` // 业务结果 - ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 - ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 - PartnerTradeNo string `json:"partner_trade_no" xml:"partner_trade_no"` // 商户订单号 - PaymentNo string `json:"payment_no" xml:"payment_no"` // 微信付款单号 - PaymentTime string `json:"payment_time" xml:"payment_time"` // 付款成功时间 + ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 + ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 + + ResultCode string `json:"result_code" xml:"result_code"` // 业务结果 + ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 + ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + + MchAppid string `json:"mch_appid" xml:"mch_appid"` // 商户appid + Mchid string `json:"mchid" xml:"mchid"` // 商户号 + DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"` // 设备号 + NonceStr string `json:"nonce_str" xml:"nonce_str"` // 随机字符串 + PartnerTradeNo string `json:"partner_trade_no" xml:"partner_trade_no"` // 商户订单号 + PaymentNo string `json:"payment_no" xml:"payment_no"` // 微信付款单号 + PaymentTime string `json:"payment_time" xml:"payment_time"` // 付款成功时间 } type TransfersResult struct { @@ -35,6 +37,7 @@ func newTransfersResult(result TransfersResponse, body []byte, http gorequest.Re // Transfers // 付款到零钱 - 付款 +// 需要证书 // https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 func (c *Client) Transfers(ctx context.Context, partnerTradeNo, openid string, amount int64, desc string) *TransfersResult { cert, err := c.P12ToPem() @@ -51,7 +54,7 @@ func (c *Client) Transfers(ctx context.Context, partnerTradeNo, openid string, a // 签名 params.Set("sign", c.getMd5Sign(params)) // 请求 - request, err := c.request(ctx, apiUrl+"/mmpaymkttransfers/promotion/transfers", params, cert) + request, err := c.request(ctx, apiUrl+"/mmpaymkttransfers/promotion/transfers", params, true, cert) // 定义 var response TransfersResponse err = xml.Unmarshal(request.ResponseBody, &response) diff --git a/service/wechatpayapiv2/pay.closeorder.go b/service/wechatpayapiv2/pay.closeorder.go new file mode 100644 index 00000000..7128b7a2 --- /dev/null +++ b/service/wechatpayapiv2/pay.closeorder.go @@ -0,0 +1,54 @@ +package wechatpayapiv2 + +import ( + "context" + "encoding/xml" + "github.com/dtapps/go-library/utils/gorandom" + "github.com/dtapps/go-library/utils/gorequest" +) + +type PayCloseOrderResponse struct { + ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 + ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 + + ResultCode string `json:"result_code,omitempty" xml:"result_code,omitempty"` // 业务结果 + ResultMsg string `json:"result_msg,omitempty" xml:"result_msg,omitempty"` // 业务结果描述 + ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 + ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + + Appid string `json:"appid,omitempty" xml:"appid,omitempty"` // 小程序ID + MchId string `json:"mch_id,omitempty" xml:"mch_id,omitempty"` // 商户号 + NonceStr string `json:"nonce_str,omitempty" xml:"nonce_str,omitempty"` // 随机字符串 + Sign string `json:"sign,omitempty" xml:"sign,omitempty"` // 签名 +} + +type PayCloseOrderResult struct { + Result PayCloseOrderResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newPayCloseOrderResult(result PayCloseOrderResponse, body []byte, http gorequest.Response, err error) *PayCloseOrderResult { + return &PayCloseOrderResult{Result: result, Body: body, Http: http, Err: err} +} + +// PayCloseOrder +// 小程序支付 - 关闭订单 +// https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_3 +func (c *Client) PayCloseOrder(ctx context.Context, outTradeNo string) *PayCloseOrderResult { + // 参数 + params := NewParams() + params.Set("appid", c.GetAppId()) // 小程序ID + params.Set("mch_id", c.GetMchId()) // 商户号 + params.Set("out_trade_no", outTradeNo) // 商户订单号 + params.Set("nonce_str", gorandom.Alphanumeric(32)) // 随机字符串 + // 签名 + params.Set("sign", c.getMd5Sign(params)) + // 请求 + request, err := c.request(ctx, apiUrl+"/pay/closeorder", params, false, nil) + // 定义 + var response PayCloseOrderResponse + err = xml.Unmarshal(request.ResponseBody, &response) + return newPayCloseOrderResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv2/pay.orderquery.go b/service/wechatpayapiv2/pay.orderquery.go new file mode 100644 index 00000000..c3ca681d --- /dev/null +++ b/service/wechatpayapiv2/pay.orderquery.go @@ -0,0 +1,79 @@ +package wechatpayapiv2 + +import ( + "context" + "encoding/xml" + "github.com/dtapps/go-library/utils/gorandom" + "github.com/dtapps/go-library/utils/gorequest" +) + +type PayOrderQueryResponse struct { + ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 + ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 + + ResultCode string `json:"result_code,omitempty" xml:"result_code,omitempty"` // 业务结果 + ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 + ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + + Appid string `json:"appid,omitempty" xml:"appid,omitempty"` // 小程序ID + MchId string `json:"mch_id,omitempty" xml:"mch_id,omitempty"` // 商户号 + NonceStr string `json:"nonce_str,omitempty" xml:"nonce_str,omitempty"` // 随机字符串 + Sign string `json:"sign,omitempty" xml:"sign,omitempty"` // 签名 + + DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"` // 设备号 + Openid string `json:"openid,omitempty" xml:"openid,omitempty"` // 用户标识 + IsSubscribe string `json:"is_subscribe,omitempty" xml:"is_subscribe,omitempty"` // 是否关注公众账号 + TradeType string `json:"trade_type,omitempty" xml:"trade_type,omitempty"` // 交易类型 + TradeState string `json:"trade_state,omitempty" xml:"trade_state,omitempty"` // 交易状态 + BankType string `json:"bank_type,omitempty" xml:"bank_type,omitempty"` // 付款银行 + TotalFee int `json:"total_fee,omitempty" xml:"total_fee,omitempty"` // 标价金额 + SettlementTotalFee int `json:"settlement_total_fee,omitempty" xml:"settlement_total_fee,omitempty"` // 应结订单金额 + FeeType string `json:"fee_type,omitempty" xml:"fee_type,omitempty"` // 标价币种 + CashFee int `json:"cash_fee,omitempty" xml:"cash_fee,omitempty"` // 现金支付金额 + CashFeeType string `json:"cash_fee_type,omitempty" xml:"cash_fee_type,omitempty"` // 现金支付币种 + CouponFee int `json:"coupon_fee,omitempty" xml:"coupon_fee,omitempty"` // 代金券金额 + CouponCount int `json:"coupon_count,omitempty" xml:"coupon_count,omitempty"` // 代金券使用数量 + CouponType string `json:"coupon_type,omitempty" xml:"coupon_type,omitempty"` // 代金券类型 + CouponId string `json:"coupon_id,omitempty" xml:"coupon_id,omitempty"` // 代金券ID + TransactionId string `json:"transaction_id,omitempty" xml:"transaction_id,omitempty"` // 微信支付订单号 + OutTradeNo string `json:"out_trade_no,omitempty" xml:"out_trade_no,omitempty"` // 商户订单号 + Attach string `json:"attach,omitempty" xml:"attach,omitempty"` // 附加数据 + TimeEnd string `json:"time_end,omitempty" xml:"time_end,omitempty"` // 支付完成时间 + TradeStateDesc string `json:"trade_state_desc,omitempty" xml:"trade_state_desc,omitempty"` // 交易状态描述 +} + +type PayOrderQueryResult struct { + Result PayOrderQueryResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newPayOrderQueryResult(result PayOrderQueryResponse, body []byte, http gorequest.Response, err error) *PayOrderQueryResult { + return &PayOrderQueryResult{Result: result, Body: body, Http: http, Err: err} +} + +// PayOrderQuery +// 小程序支付 - 查询订单 +// https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_2 +func (c *Client) PayOrderQuery(ctx context.Context, transactionId, outTradeNo string) *PayOrderQueryResult { + // 参数 + params := gorequest.NewParams() + params.Set("appid", c.GetAppId()) // 小程序ID + params.Set("mch_id", c.GetMchId()) // 商户号 + if transactionId != "" { + params.Set("transaction_id", transactionId) // 微信订单号 + } + if outTradeNo != "" { + params.Set("out_trade_no", outTradeNo) // 商户订单号 + } + params.Set("nonce_str", gorandom.Alphanumeric(32)) // 随机字符串 + // 签名 + params.Set("sign", c.getMd5Sign(params)) + // 请求 + request, err := c.request(ctx, apiUrl+"/pay/orderquery", params, false, nil) + // 定义 + var response PayOrderQueryResponse + err = xml.Unmarshal(request.ResponseBody, &response) + return newPayOrderQueryResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv2/pay.refundquery.go b/service/wechatpayapiv2/pay.refundquery.go new file mode 100644 index 00000000..d1f28aba --- /dev/null +++ b/service/wechatpayapiv2/pay.refundquery.go @@ -0,0 +1,76 @@ +package wechatpayapiv2 + +import ( + "context" + "encoding/xml" + "github.com/dtapps/go-library/utils/gorandom" + "github.com/dtapps/go-library/utils/gorequest" +) + +type PayRefundQueryResponse struct { + ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 + ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 + + ResultCode string `json:"result_code,omitempty" xml:"result_code,omitempty"` // 业务结果 + ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 + ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + + Appid string `json:"appid,omitempty" xml:"appid,omitempty"` // 小程序ID + MchId string `json:"mch_id,omitempty" xml:"mch_id,omitempty"` // 商户号 + DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"` // 设备号 + NonceStr string `json:"nonce_str,omitempty" xml:"nonce_str,omitempty"` // 随机字符串 + Sign string `json:"sign,omitempty" xml:"sign,omitempty"` // 签名 + + TotalRefundCount int `json:"total_refund_count,omitempty" xml:"total_refund_count,omitempty"` // 订单总退款次数 + TransactionId string `json:"transaction_id,omitempty" xml:"transaction_id,omitempty"` // 微信订单号 + OutTradeNo string `json:"out_trade_no,omitempty" xml:"out_trade_no,omitempty"` // 商户订单号 + TotalFee int `json:"total_fee,omitempty" xml:"total_fee,omitempty"` // 订单金额 + SettlementTotalFee int `json:"settlement_total_fee,omitempty" xml:"settlement_total_fee,omitempty"` // 应结订单金额 + FeeType string `json:"fee_type,omitempty" xml:"fee_type,omitempty"` // 货币种类 + CashFee int `json:"cash_fee,omitempty" xml:"cash_fee,omitempty"` // 现金支付金额 + RefundCount int `json:"refund_count,omitempty" xml:"refund_count,omitempty"` // 退款笔数 + OutRefundNo string `json:"out_refund_no,omitempty" xml:"out_refund_no,omitempty"` // 商户退款单号 + RefundId string `json:"refund_id,omitempty" xml:"refund_id,omitempty"` // 微信退款单号 + RefundChannel string `json:"refund_channel,omitempty" xml:"refund_channel,omitempty"` // 退款渠道 + RefundFee int `json:"refund_fee,omitempty" xml:"refund_fee,omitempty"` // 退款总金额 + CouponRefundFee int `json:"coupon_refund_fee,omitempty" xml:"coupon_refund_fee,omitempty"` // 代金券退款总金额 + SettlementRefundFee int `json:"settlement_refund_fee,omitempty" xml:"settlement_refund_fee,omitempty"` // 退款金额 + CouponType string `json:"coupon_type,omitempty" xml:"coupon_type,omitempty"` // 代金券类型 + CouponRefundCount int `json:"coupon_refund_count,omitempty" xml:"coupon_refund_count,omitempty"` // 退款代金券使用数量 + CouponRefundId string `json:"coupon_refund_id,omitempty" xml:"coupon_refund_id,omitempty"` // 退款代金券ID + RefundStatus string `json:"refund_status,omitempty" xml:"refund_status,omitempty"` // 退款状态 + RefundAccount string `json:"refund_account,omitempty" xml:"refund_account,omitempty"` // 退款资金来源 + RefundRecvAccout string `json:"refund_recv_accout,omitempty" xml:"refund_recv_accout,omitempty"` // 退款入账账户 + RefundSuccessTime string `json:"refund_success_time,omitempty" xml:"refund_success_time,omitempty"` // 退款成功时间 + CashRefundFee int `json:"cash_refund_fee,omitempty" xml:"cash_refund_fee,omitempty"` // 用户退款金额 +} + +type PayRefundQueryResult struct { + Result PayRefundQueryResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newPayRefundQueryResult(result PayRefundQueryResponse, body []byte, http gorequest.Response, err error) *PayRefundQueryResult { + return &PayRefundQueryResult{Result: result, Body: body, Http: http, Err: err} +} + +// PayRefundQuery +// 小程序支付 - 查询退款 +// https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1 +func (c *Client) PayRefundQuery(ctx context.Context, notMustParams ...gorequest.Params) *PayRefundQueryResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + params.Set("appid", c.GetAppId()) // 小程序ID + params.Set("mch_id", c.GetMchId()) // 商户号 + params.Set("nonce_str", gorandom.Alphanumeric(32)) // 随机字符串 + // 签名 + params.Set("sign", c.getMd5Sign(params)) + // 请求 + request, err := c.request(ctx, apiUrl+"/pay/unifiedorder", params, false, nil) + // 定义 + var response PayRefundQueryResponse + err = xml.Unmarshal(request.ResponseBody, &response) + return newPayRefundQueryResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv2/pay.unifiedorder.go b/service/wechatpayapiv2/pay.unifiedorder.go new file mode 100644 index 00000000..c4f79410 --- /dev/null +++ b/service/wechatpayapiv2/pay.unifiedorder.go @@ -0,0 +1,57 @@ +package wechatpayapiv2 + +import ( + "context" + "encoding/xml" + "github.com/dtapps/go-library/utils/gorandom" + "github.com/dtapps/go-library/utils/gorequest" +) + +type PayUnifiedOrderResponse struct { + ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 + ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 + + ResultCode string `json:"result_code,omitempty" xml:"result_code,omitempty"` // 业务结果 + ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 + ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + + Appid string `json:"appid,omitempty" xml:"appid,omitempty"` // 小程序ID + MchId string `json:"mch_id,omitempty" xml:"mch_id,omitempty"` // 商户号 + DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"` // 设备号 + NonceStr string `json:"nonce_str,omitempty" xml:"nonce_str,omitempty"` // 随机字符串 + Sign string `json:"sign,omitempty" xml:"sign,omitempty"` // 签名 + + TradeType string `json:"trade_type,omitempty" xml:"trade_type,omitempty"` // 交易类型 + PrepayId string `json:"prepay_id,omitempty" xml:"prepay_id,omitempty"` // 预支付交易会话标识 + CodeUrl string `json:"code_url,omitempty" xml:"code_url,omitempty"` // 二维码链接 +} + +type PayUnifiedOrderResult struct { + Result PayUnifiedOrderResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newPayUnifiedOrderResult(result PayUnifiedOrderResponse, body []byte, http gorequest.Response, err error) *PayUnifiedOrderResult { + return &PayUnifiedOrderResult{Result: result, Body: body, Http: http, Err: err} +} + +// PayUnifiedOrder +// 小程序支付 - 统一下单 +// https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1 +func (c *Client) PayUnifiedOrder(ctx context.Context, notMustParams ...gorequest.Params) *PayUnifiedOrderResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + params.Set("appid", c.GetAppId()) // 小程序ID + params.Set("mch_id", c.GetMchId()) // 商户号 + params.Set("nonce_str", gorandom.Alphanumeric(32)) // 随机字符串 + // 签名 + params.Set("sign", c.getMd5Sign(params)) + // 请求 + request, err := c.request(ctx, apiUrl+"/pay/unifiedorder", params, false, nil) + // 定义 + var response PayUnifiedOrderResponse + err = xml.Unmarshal(request.ResponseBody, &response) + return newPayUnifiedOrderResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv2/pay.unifiedorder.notify.gin.go b/service/wechatpayapiv2/pay.unifiedorder.notify.gin.go new file mode 100644 index 00000000..49e38256 --- /dev/null +++ b/service/wechatpayapiv2/pay.unifiedorder.notify.gin.go @@ -0,0 +1,48 @@ +package wechatpayapiv2 + +import ( + "context" + "github.com/gin-gonic/gin" +) + +// PayUnifiedOrderNotifyGinRequest 小程序支付 - 统一下单 - 回调通知 - 请求参数 +type PayUnifiedOrderNotifyGinRequest struct { + ReturnCode string `form:"return_code" json:"return_code" xml:"return_code" uri:"return_code" binding:"required"` // 返回状态码 + ReturnMsg string `form:"return_msg" json:"return_msg" xml:"return_msg" uri:"return_msg" binding:"omitempty"` // 返回信息 + Appid string `form:"appid" json:"appid" xml:"appid" uri:"appid" binding:"omitempty"` // 小程序ID + MchId string `form:"mch_id" json:"mch_id" xml:"mch_id" uri:"mch_id" binding:"omitempty"` // 商户号 + DeviceInfo string `form:"device_info" json:"device_info" xml:"device_info" uri:"device_info" binding:"omitempty"` // 设备号 + NonceStr string `form:"nonce_str" json:"nonce_str" xml:"nonce_str" uri:"nonce_str" binding:"omitempty"` // 随机字符串 + Sign string `form:"sign" json:"sign" xml:"sign" uri:"sign" binding:"omitempty"` // 签名 + SignType string `form:"sign_type" json:"sign_type" xml:"sign_type" uri:"sign_type" binding:"omitempty"` // 签名类型 + ResultCode string `form:"result_code" json:"result_code" xml:"result_code" uri:"result_code" binding:"omitempty"` // 业务结果 + ErrCode string `form:"err_code" json:"err_code" xml:"err_code" uri:"err_code" binding:"omitempty"` // 错误代码 + ErrCodeDes string `form:"err_code_des" json:"err_code_des" xml:"err_code_des" uri:"err_code_des" binding:"omitempty"` // 错误代码描述 + Openid string `form:"openid" json:"openid" xml:"openid" uri:"openid" binding:"omitempty"` // 用户标识 + IsSubscribe string `form:"is_subscribe" json:"is_subscribe" xml:"is_subscribe" uri:"is_subscribe" binding:"omitempty"` // 是否关注公众账号 + TradeType string `form:"trade_type" json:"trade_type" xml:"trade_type" uri:"trade_type" binding:"omitempty"` // 交易类型 + BankType string `form:"bank_type" json:"bank_type" xml:"bank_type" uri:"bank_type" binding:"omitempty"` // 付款银行 + TotalFee int `form:"total_fee" json:"total_fee" xml:"total_fee" uri:"total_fee" binding:"omitempty"` // 订单金额 + SettlementTotalFee int `form:"settlement_total_fee" json:"settlement_total_fee" xml:"settlement_total_fee" uri:"settlement_total_fee" binding:"omitempty"` // 应结订单金额 + FeeType string `form:"fee_type" json:"fee_type" xml:"fee_type" uri:"fee_type" binding:"omitempty"` // 货币种类 + CashFee int `form:"cash_fee" json:"cash_fee" xml:"cash_fee" uri:"cash_fee" binding:"omitempty"` // 现金支付金额 + CashFeeType string `form:"cash_fee_type" json:"cash_fee_type" xml:"cash_fee_type" uri:"cash_fee_type" binding:"omitempty"` // 现金支付货币类型 + CouponFee string `form:"coupon_fee" json:"coupon_fee" xml:"coupon_fee" uri:"coupon_fee" binding:"omitempty"` // 总代金券金额 + CouponCount int `form:"coupon_count" json:"coupon_count" xml:"coupon_count" uri:"coupon_count" binding:"omitempty"` // 代金券使用数量 + CouponType string `form:"coupon_type" json:"coupon_type" xml:"coupon_type" uri:"coupon_type" binding:"omitempty"` // 代金券类型 + CouponId string `form:"coupon_id" json:"coupon_id" xml:"coupon_id" uri:"coupon_id" binding:"omitempty"` // 代金券ID + TransactionId string `form:"transaction_id" json:"transaction_id" xml:"transaction_id" uri:"transaction_id" binding:"omitempty"` // 微信支付订单号 + OutTradeNo string `form:"out_trade_no" json:"out_trade_no" xml:"out_trade_no" uri:"out_trade_no" binding:"omitempty"` // 商户订单号 + Attach string `form:"attach" json:"attach" xml:"attach" uri:"attach" binding:"omitempty"` // 商家数据包 + TimeEnd string `form:"time_end" json:"time_end" xml:"time_end" uri:"time_end" binding:"omitempty"` // 支付完成时间 +} + +// PayUnifiedOrderNotifyGin 小程序支付 - 统一下单 - 回调通知 +// https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8 +func (c *Client) PayUnifiedOrderNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson PayUnifiedOrderNotifyGinRequest, err error) { + + // 解析 + err = ginCtx.ShouldBind(&validateJson) + + return validateJson, err +} diff --git a/service/wechatpayapiv2/request.go b/service/wechatpayapiv2/request.go index 073738fb..2297da04 100644 --- a/service/wechatpayapiv2/request.go +++ b/service/wechatpayapiv2/request.go @@ -7,10 +7,10 @@ import ( "github.com/dtapps/go-library/utils/gorequest" ) -func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, cert *tls.Certificate) (gorequest.Response, error) { +func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, certStatus bool, cert *tls.Certificate) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -22,7 +22,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte client.SetParams(params) // 设置证书 - client.SetP12Cert(cert) + if certStatus { + client.SetP12Cert(cert) + } // 发起请求 request, err := client.Post(ctx) @@ -30,12 +32,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddlewareXml(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddlewareXml(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.MiddlewareXml(ctx, request, go_library.Version()) } return request, err diff --git a/service/wechatpayapiv2/secapi.pay.refund.go b/service/wechatpayapiv2/secapi.pay.refund.go new file mode 100644 index 00000000..105bea87 --- /dev/null +++ b/service/wechatpayapiv2/secapi.pay.refund.go @@ -0,0 +1,73 @@ +package wechatpayapiv2 + +import ( + "context" + "encoding/xml" + "github.com/dtapps/go-library/utils/gorandom" + "github.com/dtapps/go-library/utils/gorequest" +) + +type SecApiPayRefundResponse struct { + ReturnCode string `json:"return_code" xml:"return_code"` // 返回状态码 + ReturnMsg string `json:"return_msg,omitempty" xml:"return_msg,omitempty"` // 返回信息 + + ResultCode string `json:"result_code,omitempty" xml:"result_code,omitempty"` // 业务结果 + ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"` // 错误代码 + ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"` // 错误代码描述 + + Appid string `json:"appid,omitempty" xml:"appid,omitempty"` // 小程序ID + MchId string `json:"mch_id,omitempty" xml:"mch_id,omitempty"` // 商户号 + DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"` // 设备号 + NonceStr string `json:"nonce_str,omitempty" xml:"nonce_str,omitempty"` // 随机字符串 + Sign string `json:"sign,omitempty" xml:"sign,omitempty"` // 签名 + + TotalRefundCount int `json:"total_refund_count,omitempty" xml:"total_refund_count,omitempty"` // 订单总退款次数 + TransactionId string `json:"transaction_id,omitempty" xml:"transaction_id,omitempty"` // 微信订单号 + OutTradeNo string `json:"out_trade_no,omitempty" xml:"out_trade_no,omitempty"` // 商户订单号 + OutRefundNo string `json:"out_refund_no,omitempty" xml:"out_refund_no,omitempty"` // 商户退款单号 + RefundId string `json:"refund_id,omitempty" xml:"refund_id,omitempty"` // 微信退款单号 + RefundFee int `json:"refund_fee,omitempty" xml:"refund_fee,omitempty"` // 退款金额 + SettlementRefundFee int `json:"settlement_refund_fee,omitempty" xml:"settlement_refund_fee,omitempty"` // 退款金额 + TotalFee int `json:"total_fee,omitempty" xml:"total_fee,omitempty"` // 标价金额 + SettlementTotalFee int `json:"settlement_total_fee,omitempty" xml:"settlement_total_fee,omitempty"` // 应结订单金额 + FeeType string `json:"fee_type,omitempty" xml:"fee_type,omitempty"` // 货币种类 + CashFee int `json:"cash_fee,omitempty" xml:"cash_fee,omitempty"` // 现金支付金额 + CashFeeType string `json:"cash_fee_type,omitempty" xml:"cash_fee_type,omitempty"` // 现金支付币种 + CashRefundFee int `json:"cash_refund_fee,omitempty" xml:"cash_refund_fee,omitempty"` // 现金退款金额 + CouponType string `json:"coupon_type,omitempty" xml:"coupon_type,omitempty"` // 代金券类型 + CouponRefundFee int `json:"coupon_refund_fee,omitempty" xml:"coupon_refund_fee,omitempty"` // 代金券退款总金额 + CouponRefundCount int `json:"coupon_refund_count,omitempty" xml:"coupon_refund_count,omitempty"` // 退款代金券使用数量 + CouponRefundId string `json:"coupon_refund_id,omitempty" xml:"coupon_refund_id,omitempty"` // 退款代金券ID +} + +type SecApiPayRefundResult struct { + Result SecApiPayRefundResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newSecApiPayRefundResult(result SecApiPayRefundResponse, body []byte, http gorequest.Response, err error) *SecApiPayRefundResult { + return &SecApiPayRefundResult{Result: result, Body: body, Http: http, Err: err} +} + +// SecApiPayRefund +// 小程序支付 - 申请退款 +// 需要证书 +// https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_4 +func (c *Client) SecApiPayRefund(ctx context.Context, notMustParams ...gorequest.Params) *SecApiPayRefundResult { + cert, err := c.P12ToPem() + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + params.Set("appid", c.GetAppId()) // 小程序ID + params.Set("mch_id", c.GetMchId()) // 商户号 + params.Set("nonce_str", gorandom.Alphanumeric(32)) // 随机字符串 + // 签名 + params.Set("sign", c.getMd5Sign(params)) + // 请求 + request, err := c.request(ctx, apiUrl+"/secapi/pay/refund", params, true, cert) + // 定义 + var response SecApiPayRefundResponse + err = xml.Unmarshal(request.ResponseBody, &response) + return newSecApiPayRefundResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv2/secapi.pay.refund.notify.gin.go b/service/wechatpayapiv2/secapi.pay.refund.notify.gin.go new file mode 100644 index 00000000..23bd0634 --- /dev/null +++ b/service/wechatpayapiv2/secapi.pay.refund.notify.gin.go @@ -0,0 +1,26 @@ +package wechatpayapiv2 + +import ( + "context" + "github.com/gin-gonic/gin" +) + +// SecApiPayRefundNotifyGinRequest 小程序支付 - 申请退款 - 回调通知 - 请求参数 +type SecApiPayRefundNotifyGinRequest struct { + ReturnCode string `form:"return_code" json:"return_code" xml:"return_code" uri:"return_code" binding:"required"` // 返回状态码 + ReturnMsg string `form:"return_msg" json:"return_msg" xml:"return_msg" uri:"return_msg" binding:"omitempty"` // 返回信息 + Appid string `form:"appid" json:"appid" xml:"appid" uri:"appid" binding:"omitempty"` // 公众账号ID + MchId string `form:"mch_id" json:"mch_id" xml:"mch_id" uri:"mch_id" binding:"omitempty"` // 退款的商户号 + NonceStr string `form:"nonce_str" json:"nonce_str" xml:"nonce_str" uri:"nonce_str" binding:"omitempty"` // 随机字符串 + ReqInfo string `form:"req_info" json:"req_info" xml:"req_info" uri:"req_info" binding:"omitempty"` // 加密信息 +} + +// SecApiPayRefundNotifyGin 小程序支付 - 申请退款 - 回调通知 +// https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_16&index=10 +func (c *Client) SecApiPayRefundNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson SecApiPayRefundNotifyGinRequest, err error) { + + // 解析 + err = ginCtx.ShouldBind(&validateJson) + + return validateJson, err +} diff --git a/service/wechatpayapiv3/client.go b/service/wechatpayapiv3/client.go index 9b7ad235..346a4d90 100644 --- a/service/wechatpayapiv3/client.go +++ b/service/wechatpayapiv3/client.go @@ -1,58 +1,53 @@ package wechatpayapiv3 import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppId string // 小程序或者公众号唯一凭证 - AppSecret string // 小程序或者公众号唯一凭证密钥 - MchId string // 微信支付的商户id - AesKey string // 私钥 - ApiV3 string // API v3密钥 - MchSslSerialNo string // pem 证书号 - MchSslKey string // pem key 内容 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string // 小程序或者公众号唯一凭证 + AppSecret string // 小程序或者公众号唯一凭证密钥 + MchId string // 微信支付的商户id + AesKey string // 私钥 + ApiV3 string // API v3密钥 + MchSslSerialNo string // pem 证书号 + MchSslKey string // pem key 内容 } -// Client 微信支付直连商户 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appId string // 小程序或者公众号唯一凭证 + appSecret string // 小程序或者公众号唯一凭证密钥 + mchId string // 微信支付的商户id + aesKey string // 私钥 + apiV3 string // API v3密钥 + mchSslSerialNo string // pem 证书号 + mchSslKey string // pem key 内容 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appId = config.AppId + c.config.appSecret = config.AppSecret + c.config.mchId = config.MchId + c.config.aesKey = config.AesKey + c.config.apiV3 = config.ApiV3 + c.config.mchSslSerialNo = config.MchSslSerialNo + c.config.mchSslKey = config.MchSslKey - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/wechatpayapiv3/config.go b/service/wechatpayapiv3/config.go new file mode 100644 index 00000000..375f3023 --- /dev/null +++ b/service/wechatpayapiv3/config.go @@ -0,0 +1,18 @@ +package wechatpayapiv3 + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) ConfigApp(appId, appSecret string) *Client { + c.config.appId = appId + c.config.appSecret = appSecret + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatpayapiv3/const.go b/service/wechatpayapiv3/const.go index fbdbf6cd..11347671 100644 --- a/service/wechatpayapiv3/const.go +++ b/service/wechatpayapiv3/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "wechatpayapiv3" + LogTable = "wechatpayapiv3" ) diff --git a/service/wechatpayapiv3/get.go b/service/wechatpayapiv3/get.go index ab8138cc..e49e33f8 100644 --- a/service/wechatpayapiv3/get.go +++ b/service/wechatpayapiv3/get.go @@ -1,17 +1,35 @@ package wechatpayapiv3 +import "github.com/dtapps/go-library/utils/golog" + func (c *Client) GetAppId() string { - return c.config.AppId + return c.config.appId +} + +func (c *Client) GetAppSecret() string { + return c.config.appSecret } func (c *Client) GetMchId() string { - return c.config.MchId + return c.config.mchId +} + +func (c *Client) GetAesKey() string { + return c.config.aesKey +} + +func (c *Client) GetApiV3() string { + return c.config.apiV3 } func (c *Client) GetMchSslKey() string { - return c.config.MchSslKey + return c.config.mchSslKey } func (c *Client) GetMchSslSerialNo() string { - return c.config.MchSslSerialNo + return c.config.mchSslSerialNo +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/wechatpayapiv3/pay.transactions.jsapi.go b/service/wechatpayapiv3/pay.transactions.jsapi.go index e0e31f2f..eeeba452 100644 --- a/service/wechatpayapiv3/pay.transactions.jsapi.go +++ b/service/wechatpayapiv3/pay.transactions.jsapi.go @@ -22,7 +22,7 @@ func newPayTransactionsJsapiResult(result PayTransactionsJsapiResponse, body []b return &PayTransactionsJsapiResult{Result: result, Body: body, Http: http, Err: err} } -// PayTransactionsJsapi 小程序 JSAPI下单 +// PayTransactionsJsapi JSAPI下单 // https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml func (c *Client) PayTransactionsJsapi(ctx context.Context, notMustParams ...gorequest.Params) *PayTransactionsJsapiResult { // 参数 diff --git a/service/wechatpayapiv3/pay.transactions.jsapi.notify.gin.go b/service/wechatpayapiv3/pay.transactions.jsapi.notify.gin.go new file mode 100644 index 00000000..f651ba14 --- /dev/null +++ b/service/wechatpayapiv3/pay.transactions.jsapi.notify.gin.go @@ -0,0 +1,87 @@ +package wechatpayapiv3 + +import ( + "context" + "encoding/json" + "github.com/gin-gonic/gin" +) + +// PayTransactionsJsapiNotifyGinRequest JSAPI下单 - 回调通知 - 请求参数 +type PayTransactionsJsapiNotifyGinRequest struct { + Id string `form:"id" json:"status" xml:"id" uri:"id" binding:"required"` // 通知ID + CreateTime string `form:"create_time" json:"create_time" xml:"create_time" uri:"create_time" binding:"required"` // 通知创建时间 + EventType string `form:"event_type" json:"event_type" xml:"event_type" uri:"event_type" binding:"required"` // 通知类型 + ResourceType string `form:"resource_type" json:"resource_type" xml:"resource_type" uri:"resource_type" binding:"required"` // 通知数据类型 + Resource struct { + Algorithm string `form:"algorithm" json:"algorithm" xml:"algorithm" uri:"algorithm" binding:"required"` // 加密算法类型 + Ciphertext string `form:"ciphertext" json:"ciphertext" xml:"ciphertext" uri:"ciphertext" binding:"required"` // 数据密文 + AssociatedData string `form:"associated_data" json:"associated_data" xml:"associated_data" uri:"associated_data" binding:"omitempty"` // 附加数据 + OriginalType string `form:"original_type" json:"original_type" xml:"original_type" uri:"original_type" binding:"required"` // 原始类型 + Nonce string `form:"nonce" json:"nonce" xml:"nonce" uri:"nonce" binding:"required"` // 随机串 + } `form:"resource" json:"resource" xml:"resource" uri:"resource" binding:"required"` // 通知数据 + Summary string `form:"summary" json:"summary" xml:"summary" uri:"summary" binding:"required"` // 回调摘要 +} + +// PayTransactionsJsapiNotifyGin JSAPI下单 - 回调通知 +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml +func (c *Client) PayTransactionsJsapiNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson PayTransactionsJsapiNotifyGinRequest, response PayTransactionsJsapiNotifyGinResponse, gcm []byte, err error) { + + // 解析 + err = ginCtx.ShouldBind(&validateJson) + + gcm, err = c.decryptGCM(c.GetApiV3(), validateJson.Resource.Nonce, validateJson.Resource.Ciphertext, validateJson.Resource.AssociatedData) + if err != nil { + return validateJson, response, gcm, err + } + + err = json.Unmarshal(gcm, &response) + + return validateJson, response, gcm, err +} + +// PayTransactionsJsapiNotifyGinResponse JSAPI下单 - 回调通知 - 解密后数据 +type PayTransactionsJsapiNotifyGinResponse struct { + Appid string `json:"appid"` // 应用ID + Mchid string `json:"mchid"` // 商户号 + OutTradeNo string `json:"out_trade_no"` // 商户订单号 + TransactionId string `json:"transaction_id"` // 微信支付订单号 + TradeType string `json:"trade_type"` // 交易类型 + TradeState string `json:"trade_state"` // 交易状态 + TradeStateDesc string `json:"trade_state_desc"` // 交易状态描述 + BankType string `json:"bank_type"` // 付款银行 + Attach string `json:"attach,omitempty"` // 附加数据 + SuccessTime string `json:"success_time"` // 支付完成时间 + Payer struct { + Openid string `json:"openid"` // 用户服务标识 + SpOpenid string `json:"sp_openid,omitempty"` // 用户服务标识 + SubOpenid string `json:"sub_openid,omitempty"` // 用户子标识 + } `json:"payer"` // -支付者 + Amount struct { + Total int `json:"total"` // 总金额 + PayerTotal int `json:"payer_total"` // 用户支付金额 + Currency string `json:"currency"` // 货币类型 + PayerCurrency string `json:"payer_currency"` // 用户支付币种 + } `json:"amount"` // 订单金额 + SceneInfo struct { + DeviceId string `json:"device_id,omitempty"` //商户端设备号 + } `json:"scene_info,omitempty"` // 场景信息 + PromotionDetail []struct { + CouponId string `json:"coupon_id"` // 券ID + Name string `json:"name,omitempty"` // 优惠名称 + Scope string `json:"scope,omitempty"` // 优惠范围 + Type string `json:"type,omitempty"` // 优惠类型 + Amount int `json:"amount"` // 优惠券面额 + StockId string `json:"stock_id,omitempty"` // 活动ID + WechatpayContribute int `json:"wechatpay_contribute,omitempty"` // 微信出资 + MerchantContribute int `json:"merchant_contribute,omitempty"` // 商户出资 + OtherContribute int `json:"other_contribute,omitempty"` // 其他出资 + Currency string `json:"currency,omitempty"` // 优惠币种 + GoodsDetail []struct { + GoodsId string `json:"goods_id"` // 商品编码 + Quantity int `json:"quantity"` // 商品数量 + UnitPrice int `json:"unit_price"` // 商品单价 + DiscountAmount int `json:"discount_amount"` // 商品优惠金额 + GoodsRemark string `json:"goods_remark,omitempty"` // 商品备注 + } `json:"goods_detail,omitempty"` // 单品列表 + } `json:"promotion_detail,omitempty"` // 优惠功能 +} diff --git a/service/wechatpayapiv3/refund.domestic.refunds.go b/service/wechatpayapiv3/refund.domestic.refunds.go index d282fca5..ffeaac3e 100644 --- a/service/wechatpayapiv3/refund.domestic.refunds.go +++ b/service/wechatpayapiv3/refund.domestic.refunds.go @@ -60,7 +60,8 @@ func newRefundDomesticRefundsResult(result RefundDomesticRefundsResponse, body [ return &RefundDomesticRefundsResult{Result: result, Body: body, Http: http, Err: err} } -// RefundDomesticRefunds 申请退款API https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter6_1_26.shtml +// RefundDomesticRefunds 申请退款API +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter6_1_26.shtml func (c *Client) RefundDomesticRefunds(ctx context.Context, notMustParams ...gorequest.Params) *RefundDomesticRefundsResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) diff --git a/service/wechatpayapiv3/refund.domestic.refunds.notify.gin.go b/service/wechatpayapiv3/refund.domestic.refunds.notify.gin.go new file mode 100644 index 00000000..7e3908c0 --- /dev/null +++ b/service/wechatpayapiv3/refund.domestic.refunds.notify.gin.go @@ -0,0 +1,58 @@ +package wechatpayapiv3 + +import ( + "context" + "encoding/json" + "github.com/gin-gonic/gin" +) + +// RefundDomesticRefundsNotifyGinRequest 申请退款API - 回调通知 - 请求参数 +type RefundDomesticRefundsNotifyGinRequest struct { + Id string `form:"id" json:"status" xml:"id" uri:"id" binding:"required"` // 通知ID + CreateTime string `form:"create_time" json:"create_time" xml:"create_time" uri:"create_time" binding:"required"` // 通知创建时间 + EventType string `form:"event_type" json:"event_type" xml:"event_type" uri:"event_type" binding:"required"` // 通知类型 + Summary string `form:"summary" json:"summary" xml:"summary" uri:"summary" binding:"required"` // 通知简要说明 + ResourceType string `form:"resource_type" json:"resource_type" xml:"resource_type" uri:"resource_type" binding:"required"` // 通知数据类型 + Resource struct { + Algorithm string `form:"algorithm" json:"algorithm" xml:"algorithm" uri:"algorithm" binding:"required"` // 加密算法类型 + Ciphertext string `form:"ciphertext" json:"ciphertext" xml:"ciphertext" uri:"ciphertext" binding:"required"` // 数据密文 + AssociatedData string `form:"associated_data" json:"associated_data" xml:"associated_data" uri:"associated_data" binding:"omitempty"` // 附加数据 + OriginalType string `form:"original_type" json:"original_type" xml:"original_type" uri:"original_type" binding:"required"` // 原始类型 + Nonce string `form:"nonce" json:"nonce" xml:"nonce" uri:"nonce" binding:"required"` // 随机串 + } `form:"resource" json:"resource" xml:"resource" uri:"resource" binding:"required"` // 通知数据 +} + +// RefundDomesticRefundsNotifyGin 申请退款API - 回调通知 +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter6_1_26.shtml +func (c *Client) RefundDomesticRefundsNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson RefundDomesticRefundsNotifyGinRequest, response RefundDomesticRefundsNotifyGinResponse, gcm []byte, err error) { + + // 解析 + err = ginCtx.ShouldBind(&validateJson) + + gcm, err = c.decryptGCM(c.GetApiV3(), validateJson.Resource.Nonce, validateJson.Resource.Ciphertext, validateJson.Resource.AssociatedData) + if err != nil { + return validateJson, response, gcm, err + } + + err = json.Unmarshal(gcm, &response) + + return validateJson, response, gcm, err +} + +// RefundDomesticRefundsNotifyGinResponse 申请退款API - 回调通知 - 解密后数据 +type RefundDomesticRefundsNotifyGinResponse struct { + Mchid string `json:"mchid"` // 直连商户号 + OutTradeNo string `json:"out_trade_no"` // 商户订单号 + TransactionId string `json:"transaction_id"` // 微信支付订单号 + OutRefundNo string `json:"out_refund_no"` // 商户退款单号 + RefundId string `json:"refund_id"` // 微信支付退款单号 + RefundStatus string `json:"refund_status"` // 退款状态 + SuccessTime string `json:"success_time"` // 退款成功时间 + UserReceivedAccount string `json:"user_received_account"` // 退款入账账户 + Amount struct { + Total int `json:"total"` // 订单金额 + Refund int `json:"refund"` // 退款金额 + PayerTotal int `json:"payer_total"` // 用户支付金额 + PayerRefund int `json:"payer_refund"` // 用户退款金额 + } `json:"amount"` // 金额信息 +} diff --git a/service/wechatpayapiv3/refund.domestic.refunds.out_refund_no.go b/service/wechatpayapiv3/refund.domestic.refunds.out_refund_no.go index c2666a40..d8eb5c9d 100644 --- a/service/wechatpayapiv3/refund.domestic.refunds.out_refund_no.go +++ b/service/wechatpayapiv3/refund.domestic.refunds.out_refund_no.go @@ -61,7 +61,8 @@ func newRefundDomesticRefundsOutRefundNoResult(result RefundDomesticRefundsOutRe return &RefundDomesticRefundsOutRefundNoResult{Result: result, Body: body, Http: http, Err: err} } -// RefundDomesticRefundsOutRefundNo 查询单笔退款API https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_10.shtml +// RefundDomesticRefundsOutRefundNo 查询单笔退款API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_10.shtml func (c *Client) RefundDomesticRefundsOutRefundNo(ctx context.Context, outRefundNo string) *RefundDomesticRefundsOutRefundNoResult { // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/refund/domestic/refunds/%s", outRefundNo), map[string]interface{}{}, http.MethodGet, true) diff --git a/service/wechatpayapiv3/request.go b/service/wechatpayapiv3/request.go index 7541ec18..08e6461c 100644 --- a/service/wechatpayapiv3/request.go +++ b/service/wechatpayapiv3/request.go @@ -24,7 +24,7 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte } // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -52,12 +52,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/wechatpayapiv3/set.go b/service/wechatpayapiv3/set.go deleted file mode 100644 index a1ae8905..00000000 --- a/service/wechatpayapiv3/set.go +++ /dev/null @@ -1,9 +0,0 @@ -package wechatpayapiv3 - -func (c *Client) SetAppId(appId string) { - c.config.AppId = appId -} - -func (c *Client) SetAppSecret(appSecret string) { - c.config.AppSecret = appSecret -} diff --git a/service/wechatpayapiv3/sign.decrypt.go b/service/wechatpayapiv3/sign.decrypt.go new file mode 100644 index 00000000..279efde4 --- /dev/null +++ b/service/wechatpayapiv3/sign.decrypt.go @@ -0,0 +1,5 @@ +package wechatpayapiv3 + +func (c *Client) SignDecrypt(aesKey, associatedData, nonce, ciphertext string) ([]byte, error) { + return c.decryptGCM(aesKey, nonce, ciphertext, associatedData) +} diff --git a/service/wechatpayapiv3/transfer.batches.batch-id.details.detail-id.go b/service/wechatpayapiv3/transfer.batches.batch-id.details.detail-id.go new file mode 100644 index 00000000..48795cd7 --- /dev/null +++ b/service/wechatpayapiv3/transfer.batches.batch-id.details.detail-id.go @@ -0,0 +1,53 @@ +package wechatpayapiv3 + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" + "time" +) + +type TransferBatchesBatchIdDetailsDetailIdResponse struct { + Mchid string `json:"mchid"` // 商户号 + OutBatchNo string `json:"out_batch_no"` // 商家批次单号 + BatchId string `json:"batch_id"` // 微信批次单号 + Appid string `json:"appid"` // 直连商户的appid + OutDetailNo string `json:"out_detail_no"` // 商家明细单号 + DetailId string `json:"detail_id"` // 微信明细单号 + DetailStatus string `json:"detail_status"` // 明细状态 + TransferAmount int `json:"transfer_amount"` // 转账金额 + TransferRemark string `json:"transfer_remark"` // 转账备注 + FailReason string `json:"fail_reason"` // 明细失败原因 + Openid string `json:"openid"` // 用户在直连商户应用下的用户标示 + UserName string `json:"user_name"` // 收款用户姓名 + InitiateTime time.Time `json:"initiate_time"` // 转账发起时间 + UpdateTime time.Time `json:"update_time"` // 明细更新时间 +} + +type TransferBatchesBatchIdDetailsDetailIdResult struct { + Result TransferBatchesBatchIdDetailsDetailIdResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newTransferBatchesBatchIdDetailsDetailIdResult(result TransferBatchesBatchIdDetailsDetailIdResponse, body []byte, http gorequest.Response, err error) *TransferBatchesBatchIdDetailsDetailIdResult { + return &TransferBatchesBatchIdDetailsDetailIdResult{Result: result, Body: body, Http: http, Err: err} +} + +// TransferBatchesBatchIdDetailsDetailId 微信明细单号查询明细单API +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_3.shtml +func (c *Client) TransferBatchesBatchIdDetailsDetailId(ctx context.Context, batchId string, detailId string) *TransferBatchesBatchIdDetailsDetailIdResult { + // 参数 + params := gorequest.NewParams() + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/transfer/batches/batch-id/"+batchId+"details/detail-id/"+detailId, params, http.MethodGet, false) + if err != nil { + return newTransferBatchesBatchIdDetailsDetailIdResult(TransferBatchesBatchIdDetailsDetailIdResponse{}, request.ResponseBody, request, err) + } + // 定义 + var response TransferBatchesBatchIdDetailsDetailIdResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newTransferBatchesBatchIdDetailsDetailIdResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv3/transfer.batches.batch-id.go b/service/wechatpayapiv3/transfer.batches.batch-id.go new file mode 100644 index 00000000..88e994e9 --- /dev/null +++ b/service/wechatpayapiv3/transfer.batches.batch-id.go @@ -0,0 +1,71 @@ +package wechatpayapiv3 + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type TransferBatchesBatchIdResponse struct { + TransferBatch struct { + Mchid string `json:"mchid"` // 商户号 + OutBatchNo string `json:"out_batch_no"` // 商家批次单号 + BatchId string `json:"batch_id"` // 微信批次单号 + Appid string `json:"appid"` // 直连商户的appid + BatchStatus string `json:"batch_status"` // 批次状态 + BatchType string `json:"batch_type"` // 批次类型 + BatchName string `json:"batch_name"` // 批次名称 + BatchRemark string `json:"batch_remark"` // 批次备注 + CloseReason string `json:"close_reason,omitempty"` // 批次关闭原因 + TotalAmount int `json:"total_amount"` // 转账总金额 + TotalNum int `json:"total_num"` // 转账总笔数 + CreateTime string `json:"create_time"` // 批次创建时间 + UpdateTime string `json:"update_time"` // 批次更新时间 + SuccessAmount int `json:"success_amount"` // 转账成功金额 + SuccessNum int `json:"success_num"` // 转账成功笔数 + FailAmount int `json:"fail_amount"` // 转账失败金额 + FailNum int `json:"fail_num"` // 转账失败笔数 + } `json:"transfer_batch"` // 转账批次单 + TransferDetailList []struct { + DetailId string `json:"detail_id"` // 微信明细单号 + OutDetailNo string `json:"out_detail_no"` // 商家明细单号 + DetailStatus string `json:"detail_status"` // 明细状态 + } `json:"transfer_detail_list,omitempty"` // 转账明细单列表 + Offset int `json:"offset,omitempty"` // 请求资源起始位置 + Limit int `json:"limit,omitempty"` // 最大资源条数 +} + +type TransferBatchesBatchIdResult struct { + Result TransferBatchesBatchIdResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newTransferBatchesBatchIdResult(result TransferBatchesBatchIdResponse, body []byte, http gorequest.Response, err error) *TransferBatchesBatchIdResult { + return &TransferBatchesBatchIdResult{Result: result, Body: body, Http: http, Err: err} +} + +// TransferBatchesBatchId 微信批次单号查询批次单API +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_2.shtml +func (c *Client) TransferBatchesBatchId(ctx context.Context, batchId string, needQueryDetail bool, offset, limit int, detailStatus string) *TransferBatchesBatchIdResult { + // 参数 + params := gorequest.NewParams() + params.Set("batch_id", batchId) + params.Set("need_query_detail", needQueryDetail) + params.Set("offset", offset) + params.Set("limit", limit) + if needQueryDetail { + params.Set("detail_status", detailStatus) + } + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/transfer/batches/batch-id/"+batchId, params, http.MethodGet, false) + if err != nil { + return newTransferBatchesBatchIdResult(TransferBatchesBatchIdResponse{}, request.ResponseBody, request, err) + } + // 定义 + var response TransferBatchesBatchIdResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newTransferBatchesBatchIdResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv3/transfer.batches.go b/service/wechatpayapiv3/transfer.batches.go new file mode 100644 index 00000000..76dc0582 --- /dev/null +++ b/service/wechatpayapiv3/transfer.batches.go @@ -0,0 +1,42 @@ +package wechatpayapiv3 + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type TransferBatchesResponse struct { + OutBatchNo string `json:"out_batch_no"` // 商家批次单号 + BatchId string `json:"batch_id"` // 微信批次单号 + CreateTime string `json:"create_time"` // 批次创建时间 +} + +type TransferBatchesResult struct { + Result TransferBatchesResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newTransferBatchesResult(result TransferBatchesResponse, body []byte, http gorequest.Response, err error) *TransferBatchesResult { + return &TransferBatchesResult{Result: result, Body: body, Http: http, Err: err} +} + +// TransferBatches 发起商家转账API +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml +func (c *Client) TransferBatches(ctx context.Context, notMustParams ...gorequest.Params) *TransferBatchesResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + params.Set("appid", c.GetAppId()) + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/transfer/batches", params, http.MethodPost, false) + if err != nil { + return newTransferBatchesResult(TransferBatchesResponse{}, request.ResponseBody, request, err) + } + // 定义 + var response TransferBatchesResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newTransferBatchesResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv3/transfer.batches.out-batch-no.details.out-detail-no.go b/service/wechatpayapiv3/transfer.batches.out-batch-no.details.out-detail-no.go new file mode 100644 index 00000000..f8def5d9 --- /dev/null +++ b/service/wechatpayapiv3/transfer.batches.out-batch-no.details.out-detail-no.go @@ -0,0 +1,52 @@ +package wechatpayapiv3 + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" + "time" +) + +type TransferBatchesOutBatchNoDetailsOutDetailResponse struct { + OutBatchNo string `json:"out_batch_no"` // 商家批次单号 + BatchId string `json:"batch_id"` // 微信批次单号 + Appid string `json:"appid"` // 直连商户的appid + OutDetailNo string `json:"out_detail_no"` // 商家明细单号 + DetailId string `json:"detail_id"` // 微信明细单号 + DetailStatus string `json:"detail_status"` // 明细状态 + TransferAmount int `json:"transfer_amount"` // 转账金额 + TransferRemark string `json:"transfer_remark"` // 转账备注 + FailReason string `json:"fail_reason"` // 明细失败原因 + Openid string `json:"openid"` // 用户在直连商户应用下的用户标示 + UserName string `json:"user_name"` // 收款用户姓名 + InitiateTime time.Time `json:"initiate_time"` // 转账发起时间 + UpdateTime time.Time `json:"update_time"` // 明细更新时间 +} + +type TransferBatchesOutBatchNoDetailsOutDetailResult struct { + Result TransferBatchesOutBatchNoDetailsOutDetailResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newTransferBatchesOutBatchNoDetailsOutDetailResult(result TransferBatchesOutBatchNoDetailsOutDetailResponse, body []byte, http gorequest.Response, err error) *TransferBatchesOutBatchNoDetailsOutDetailResult { + return &TransferBatchesOutBatchNoDetailsOutDetailResult{Result: result, Body: body, Http: http, Err: err} +} + +// TransferBatchesOutBatchNoDetailsOutDetail 商家明细单号查询明细单API +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_6.shtml +func (c *Client) TransferBatchesOutBatchNoDetailsOutDetail(ctx context.Context, outBatchNo string, outDetailNo string) *TransferBatchesOutBatchNoDetailsOutDetailResult { + // 参数 + params := gorequest.NewParams() + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/transfer/batches/out-batch-no/"+outBatchNo+"details/out-detail-no//"+outDetailNo, params, http.MethodGet, false) + if err != nil { + return newTransferBatchesOutBatchNoDetailsOutDetailResult(TransferBatchesOutBatchNoDetailsOutDetailResponse{}, request.ResponseBody, request, err) + } + // 定义 + var response TransferBatchesOutBatchNoDetailsOutDetailResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newTransferBatchesOutBatchNoDetailsOutDetailResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayapiv3/transfer.batches.out-batch-no.go b/service/wechatpayapiv3/transfer.batches.out-batch-no.go new file mode 100644 index 00000000..06561684 --- /dev/null +++ b/service/wechatpayapiv3/transfer.batches.out-batch-no.go @@ -0,0 +1,71 @@ +package wechatpayapiv3 + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type TransferBatchesOutBatchNoResponse struct { + TransferBatch struct { + Mchid string `json:"mchid"` // 商户号 + OutBatchNo string `json:"out_batch_no"` // 商家批次单号 + BatchId string `json:"batch_id"` // 微信批次单号 + Appid string `json:"appid"` // 直连商户的appid + BatchStatus string `json:"batch_status"` // 批次状态 + BatchType string `json:"batch_type"` // 批次类型 + BatchName string `json:"batch_name"` // 批次名称 + BatchRemark string `json:"batch_remark"` // 批次备注 + CloseReason string `json:"close_reason,omitempty"` // 批次关闭原因 + TotalAmount int `json:"total_amount"` // 转账总金额 + TotalNum int `json:"total_num"` // 转账总笔数 + CreateTime string `json:"create_time"` // 批次创建时间 + UpdateTime string `json:"update_time"` // 批次更新时间 + SuccessAmount int `json:"success_amount"` // 转账成功金额 + SuccessNum int `json:"success_num"` // 转账成功笔数 + FailAmount int `json:"fail_amount"` // 转账失败金额 + FailNum int `json:"fail_num"` // 转账失败笔数 + } `json:"transfer_batch"` // 转账批次单 + TransferDetailList []struct { + DetailId string `json:"detail_id"` // 微信明细单号 + OutDetailNo string `json:"out_detail_no"` // 商家明细单号 + DetailStatus string `json:"detail_status"` // 明细状态 + } `json:"transfer_detail_list,omitempty"` // 转账明细单列表 + Offset int `json:"offset"` // 请求资源起始位置 + Limit int `json:"limit"` // 最大资源条数 +} + +type TransferBatchesOutBatchNoResult struct { + Result TransferBatchesOutBatchNoResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 +} + +func newTransferBatchesOutBatchNoResult(result TransferBatchesOutBatchNoResponse, body []byte, http gorequest.Response, err error) *TransferBatchesOutBatchNoResult { + return &TransferBatchesOutBatchNoResult{Result: result, Body: body, Http: http, Err: err} +} + +// TransferBatchesOutBatchNo 商家批次单号查询批次单API +// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_5.shtml +func (c *Client) TransferBatchesOutBatchNo(ctx context.Context, outBatchNo string, needQueryDetail bool, offset, limit int, detailStatus string) *TransferBatchesOutBatchNoResult { + // 参数 + params := gorequest.NewParams() + params.Set("out_batch_no", outBatchNo) + params.Set("need_query_detail", needQueryDetail) + params.Set("offset", offset) + params.Set("limit", limit) + if needQueryDetail { + params.Set("detail_status", detailStatus) + } + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/transfer/batches/out-batch-no/"+outBatchNo, params, http.MethodGet, false) + if err != nil { + return newTransferBatchesOutBatchNoResult(TransferBatchesOutBatchNoResponse{}, request.ResponseBody, request, err) + } + // 定义 + var response TransferBatchesOutBatchNoResponse + err = json.Unmarshal(request.ResponseBody, &response) + return newTransferBatchesOutBatchNoResult(response, request.ResponseBody, request, err) +} diff --git a/service/wechatpayopen/client.go b/service/wechatpayopen/client.go index 653273af..69808129 100644 --- a/service/wechatpayopen/client.go +++ b/service/wechatpayopen/client.go @@ -1,62 +1,58 @@ package wechatpayopen import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - SpAppid string // 服务商应用ID - SpMchId string // 服务商户号 - SubAppid string // 子商户应用ID - SubMchId string // 子商户号 - ApiV2 string // APIv2密钥 - ApiV3 string // APIv3密钥 - SerialNo string // 序列号 - MchSslSerialNo string // pem 证书号 - MchSslCer string // pem 内容 - MchSslKey string // pem key 内容 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + SpAppid string // 服务商应用ID + SpMchId string // 服务商户号 + ApiV2 string // APIv2密钥 + ApiV3 string // APIv3密钥 + SerialNo string // 序列号 + MchSslSerialNo string // pem 证书号 + MchSslCer string // pem 内容 + MchSslKey string // pem key 内容 } -// Client 微信支付服务 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + spAppid string // 服务商应用ID + spMchId string // 服务商户号 + subAppid string // 子商户应用ID + subMchId string // 子商户号 + apiV2 string // APIv2密钥 + apiV3 string // APIv3密钥 + serialNo string // 序列号 + mchSslSerialNo string // pem 证书号 + mchSslCer string // pem 内容 + mchSslKey string // pem key 内容 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -// NewClient 实例化 -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.spAppid = config.SpAppid + c.config.spMchId = config.SpMchId + c.config.apiV2 = config.ApiV2 + c.config.apiV3 = config.ApiV3 + c.config.serialNo = config.SerialNo + c.config.mchSslSerialNo = config.MchSslSerialNo + c.config.mchSslCer = config.MchSslCer + c.config.mchSslKey = config.MchSslKey - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/wechatpayopen/config.go b/service/wechatpayopen/config.go new file mode 100644 index 00000000..5bd5ee53 --- /dev/null +++ b/service/wechatpayopen/config.go @@ -0,0 +1,14 @@ +package wechatpayopen + +import ( + "github.com/dtapps/go-library/utils/golog" +) + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatpayopen/const.go b/service/wechatpayopen/const.go index 79e5fe12..11071a9c 100644 --- a/service/wechatpayopen/const.go +++ b/service/wechatpayopen/const.go @@ -1,36 +1,14 @@ package wechatpayopen -import "time" - // 微信支付 API 地址 const ( apiUrl = "https://api.mch.weixin.qq.com" WechatPayAPIServerBackup = "https://api2.mch.weixin.qq.com" // 微信支付 API 备份地址 ) +// SDK 相关信息 const ( - logTable = "wechatpayopen" -) - -const ( - UserAgentFormat = "WechatPay-Go/%s (%s) GO/%s" // UserAgent中的信息 -) - -// HTTP 请求报文 Header 相关常量 -const ( - Authorization = "Authorization" // Header 中的 Authorization 字段 - Accept = "Accept" // Header 中的 Accept 字段 - ContentType = "Content-Type" // Header 中的 ContentType 字段 - ContentLength = "Content-Length" // Header 中的 ContentLength 字段 - UserAgent = "User-Agent" // Header 中的 UserAgent 字段 -) - -// 常用 ContentType -const ( - ApplicationJSON = "application/json" - ImageJPG = "image/jpg" - ImagePNG = "image/png" - VideoMP4 = "video/mp4" + LogTable = "wechatpayopen" ) // 请求报文签名相关常量 @@ -40,21 +18,6 @@ const ( HeaderAuthorizationFormat = "%s mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\"" ) -// HTTP 应答报文 Header 相关常量 -const ( - WechatPayTimestamp = "Wechatpay-Timestamp" // 微信支付回包时间戳 - WechatPayNonce = "Wechatpay-Nonce" // 微信支付回包随机字符串 - WechatPaySignature = "Wechatpay-Signature" // 微信支付回包签名信息 - WechatPaySerial = "Wechatpay-Serial" // 微信支付回包平台序列号 - RequestID = "Request-Id" // 微信支付回包请求ID -) - -// 时间相关常量 -const ( - FiveMinute = 5 * 60 // 回包校验最长时间(秒) - DefaultTimeout = 30 * time.Second // HTTP 请求默认超时时间 -) - func getAuthorizationType() string { return "WECHATPAY2-" + algorithm() } @@ -64,11 +27,26 @@ func algorithm() string { return "SHA256-RSA2048" } +// 接口状态 const ( - CodeSuccess = "SUCCESS" + CodeSUCCESS = "SUCCESS" // 支付成功 退款成功 + CodeREFUND = "REFUND" // 转入退款 + CodeNOTPAY = "NOTPAY" // 未支付 + CodeCLOSED = "CLOSED" // 已关闭 退款关闭 + CodeREVOKED = "REVOKED" // 已撤销 + CodeUSERPAYING = "USERPAYING" // 用户支付中 + CodePAYERROR = "PAYERROR" // 支付失败 + CodePROCESSING = "PROCESSING" // 退款处理中 + CodeABNORMAL = "ABNORMAL" // 退款异常 ) type ApiError struct { Code string `json:"code"` Message string `json:"message"` } + +const ( + MERCHANT_ID = "MERCHANT_ID" + PERSONAL_OPENID = "PERSONAL_OPENID" + PERSONAL_SUB_OPENID = "PERSONAL_SUB_OPENID" +) diff --git a/service/wechatpayopen/ecommerce.fund.balance.go b/service/wechatpayopen/ecommerce.fund.balance.go index 980f88e2..4e0a40f2 100644 --- a/service/wechatpayopen/ecommerce.fund.balance.go +++ b/service/wechatpayopen/ecommerce.fund.balance.go @@ -33,7 +33,7 @@ func (c *Client) EcommerceFundBalance(ctx context.Context, accountType string) * // 参数 params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/ecommerce/fund/balance/%s?account_type=%s", c.config.SubMchId, accountType), params, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/ecommerce/fund/balance/%s?account_type=%s", c.GetSubMchId(), accountType), params, http.MethodGet) if err != nil { return newEcommerceFundBalanceResult(EcommerceFundBalanceResponse{}, request.ResponseBody, request, err) } diff --git a/service/wechatpayopen/ecommerce.fund.enddaybalance.go b/service/wechatpayopen/ecommerce.fund.enddaybalance.go index 361e57a3..d292e88a 100644 --- a/service/wechatpayopen/ecommerce.fund.enddaybalance.go +++ b/service/wechatpayopen/ecommerce.fund.enddaybalance.go @@ -32,7 +32,7 @@ func (c *Client) EcommerceFundEndDayBalance(ctx context.Context, date string) *E // 参数 params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/ecommerce/fund/enddaybalance/%s?date=%s", c.config.SubMchId, date), params, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/ecommerce/fund/enddaybalance/%s?date=%s", c.GetSubMchId(), date), params, http.MethodGet) if err != nil { return newEcommerceFundEndDayBalanceResult(EcommerceFundEndDayBalanceResponse{}, request.ResponseBody, request, err) } diff --git a/service/wechatpayopen/get.go b/service/wechatpayopen/get.go index df195fa4..e980808b 100644 --- a/service/wechatpayopen/get.go +++ b/service/wechatpayopen/get.go @@ -1,17 +1,35 @@ package wechatpayopen +import "github.com/dtapps/go-library/utils/golog" + func (c *Client) GetSpAppid() string { - return c.config.SpAppid + return c.config.spAppid } func (c *Client) GetSpMchId() string { - return c.config.SpMchId + return c.config.spMchId } func (c *Client) GetSubAppid() string { - return c.config.SubAppid + return c.config.subAppid } func (c *Client) GetSubMchId() string { - return c.config.SubMchId + return c.config.subMchId +} + +func (c *Client) GetMchSslKey() string { + return c.config.mchSslKey +} + +func (c *Client) GetMchSslSerialNo() string { + return c.config.mchSslSerialNo +} + +func (c *Client) GetApiV3() string { + return c.config.apiV3 +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/wechatpayopen/merchant.fund.balance.go b/service/wechatpayopen/merchant.fund.balance.go index c293eece..a5d2a666 100644 --- a/service/wechatpayopen/merchant.fund.balance.go +++ b/service/wechatpayopen/merchant.fund.balance.go @@ -14,14 +14,15 @@ type MerchantFundBalanceResponse struct { } type MerchantFundBalanceResult struct { - Result MerchantFundBalanceResponse // 结果 - Body []byte // 内容 - Http gorequest.Response // 请求 - Err error // 错误 + Result MerchantFundBalanceResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 } -func newMerchantFundBalanceResult(result MerchantFundBalanceResponse, body []byte, http gorequest.Response, err error) *MerchantFundBalanceResult { - return &MerchantFundBalanceResult{Result: result, Body: body, Http: http, Err: err} +func newMerchantFundBalanceResult(result MerchantFundBalanceResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *MerchantFundBalanceResult { + return &MerchantFundBalanceResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} } // MerchantFundBalance 查询电商平台账户实时余额API @@ -33,10 +34,13 @@ func (c *Client) MerchantFundBalance(ctx context.Context, accountType string) *M // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/merchant/fund/balance/%s", accountType), params, http.MethodGet) if err != nil { - return newMerchantFundBalanceResult(MerchantFundBalanceResponse{}, request.ResponseBody, request, err) + return newMerchantFundBalanceResult(MerchantFundBalanceResponse{}, request.ResponseBody, request, err, ApiError{}) } // 定义 var response MerchantFundBalanceResponse err = json.Unmarshal(request.ResponseBody, &response) - return newMerchantFundBalanceResult(response, request.ResponseBody, request, err) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newMerchantFundBalanceResult(response, request.ResponseBody, request, err, apiError) } diff --git a/service/wechatpayopen/merchant.fund.dayendbalance.go b/service/wechatpayopen/merchant.fund.dayendbalance.go index 0566da36..873b3808 100644 --- a/service/wechatpayopen/merchant.fund.dayendbalance.go +++ b/service/wechatpayopen/merchant.fund.dayendbalance.go @@ -14,14 +14,15 @@ type MerchantFundDayEndBalanceResponse struct { } type MerchantFundDayEndBalanceResult struct { - Result MerchantFundDayEndBalanceResponse // 结果 - Body []byte // 内容 - Http gorequest.Response // 请求 - Err error // 错误 + Result MerchantFundDayEndBalanceResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 } -func newMerchantFundDayEndBalanceResult(result MerchantFundDayEndBalanceResponse, body []byte, http gorequest.Response, err error) *MerchantFundDayEndBalanceResult { - return &MerchantFundDayEndBalanceResult{Result: result, Body: body, Http: http, Err: err} +func newMerchantFundDayEndBalanceResult(result MerchantFundDayEndBalanceResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *MerchantFundDayEndBalanceResult { + return &MerchantFundDayEndBalanceResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} } // MerchantFundDayEndBalance 查询电商平台账户日终余额API @@ -34,10 +35,13 @@ func (c *Client) MerchantFundDayEndBalance(ctx context.Context, accountType, dat // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/merchant/fund/dayendbalance/%s?date=%s", accountType, date), params, http.MethodGet) if err != nil { - return newMerchantFundDayEndBalanceResult(MerchantFundDayEndBalanceResponse{}, request.ResponseBody, request, err) + return newMerchantFundDayEndBalanceResult(MerchantFundDayEndBalanceResponse{}, request.ResponseBody, request, err, ApiError{}) } // 定义 var response MerchantFundDayEndBalanceResponse err = json.Unmarshal(request.ResponseBody, &response) - return newMerchantFundDayEndBalanceResult(response, request.ResponseBody, request, err) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newMerchantFundDayEndBalanceResult(response, request.ResponseBody, request, err, apiError) } diff --git a/service/wechatpayopen/pay.jsapi.go b/service/wechatpayopen/pay.jsapi.go index 6bb38a3b..e6eca21b 100644 --- a/service/wechatpayopen/pay.jsapi.go +++ b/service/wechatpayopen/pay.jsapi.go @@ -29,15 +29,15 @@ func (c *Client) GetJsApi(ctx context.Context, param GetJsApi) (result GetJsApiR timeStamp := time.Now().Unix() nonce := gorandom.Alphanumeric(32) - result.AppId = c.config.SubAppid + result.AppId = c.GetSubAppid() result.TimeStamp = fmt.Sprintf("%v", timeStamp) // 时间戳 result.NonceStr = nonce // 随机字符串 result.Package = param.Package // 订单详情扩展字符串 // 签名 - message := fmt.Sprintf("%s\n%s\n%s\n%s\n", c.config.SubAppid, fmt.Sprintf("%v", timeStamp), nonce, param.Package) + message := fmt.Sprintf("%s\n%s\n%s\n%s\n", c.GetSubAppid(), fmt.Sprintf("%v", timeStamp), nonce, param.Package) - signBytes, err := c.signPKCS1v15(message, []byte(c.config.MchSslKey)) + signBytes, err := c.signPKCS1v15(message, []byte(c.GetMchSslKey())) if err != nil { return result, err } diff --git a/service/wechatpayopen/pay.partner.transactions.h5.go b/service/wechatpayopen/pay.partner.transactions.h5.go index 4c548bba..42d86cf1 100644 --- a/service/wechatpayopen/pay.partner.transactions.h5.go +++ b/service/wechatpayopen/pay.partner.transactions.h5.go @@ -28,10 +28,10 @@ func newPayPartnerTransactionsH5Result(result PayPartnerTransactionsH5Response, func (c *Client) PayPartnerTransactionsH5(ctx context.Context, notMustParams ...gorequest.Params) *PayPartnerTransactionsH5Result { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("sp_appid", c.config.SpAppid) // 服务商应用ID - params.Set("sp_mchid", c.config.SpMchId) // 服务商户号 - params.Set("sub_appid", c.config.SubAppid) // 子商户应用ID - params.Set("sub_mchid", c.config.SubMchId) // 子商户号 + params.Set("sp_appid", c.GetSpAppid()) // 服务商应用ID + params.Set("sp_mchid", c.GetSpMchId()) // 服务商户号 + params.Set("sub_appid", c.GetSubAppid()) // 子商户应用ID + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 // 请求 request, err := c.request(ctx, apiUrl+"/v3/pay/partner/transactions/h5", params, http.MethodPost) if err != nil { diff --git a/service/wechatpayopen/pay.partner.transactions.id.go b/service/wechatpayopen/pay.partner.transactions.id.go index 653590c1..67915e7c 100644 --- a/service/wechatpayopen/pay.partner.transactions.id.go +++ b/service/wechatpayopen/pay.partner.transactions.id.go @@ -53,14 +53,15 @@ type PayPartnerTransactionsIdResponse struct { } type PayPartnerTransactionsIdResult struct { - Result PayPartnerTransactionsIdResponse // 结果 - Body []byte // 内容 - Http gorequest.Response // 请求 - Err error // 错误 + Result PayPartnerTransactionsIdResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 } -func newPayPartnerTransactionsIdResult(result PayPartnerTransactionsIdResponse, body []byte, http gorequest.Response, err error) *PayPartnerTransactionsIdResult { - return &PayPartnerTransactionsIdResult{Result: result, Body: body, Http: http, Err: err} +func newPayPartnerTransactionsIdResult(result PayPartnerTransactionsIdResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *PayPartnerTransactionsIdResult { + return &PayPartnerTransactionsIdResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} } // PayPartnerTransactionsId 微信支付订单号查询 @@ -69,12 +70,15 @@ func (c *Client) PayPartnerTransactionsId(ctx context.Context, transactionId str // 参数 params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/pay/partner/transactions/id/%s?sp_mchid=%s&sub_mchid=%s", transactionId, c.config.SpMchId, c.config.SubMchId), params, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/pay/partner/transactions/id/%s?sp_mchid=%s&sub_mchid=%s", transactionId, c.GetSpMchId(), c.GetSubMchId()), params, http.MethodGet) if err != nil { - return newPayPartnerTransactionsIdResult(PayPartnerTransactionsIdResponse{}, request.ResponseBody, request, err) + return newPayPartnerTransactionsIdResult(PayPartnerTransactionsIdResponse{}, request.ResponseBody, request, err, ApiError{}) } // 定义 var response PayPartnerTransactionsIdResponse err = json.Unmarshal(request.ResponseBody, &response) - return newPayPartnerTransactionsIdResult(response, request.ResponseBody, request, err) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newPayPartnerTransactionsIdResult(response, request.ResponseBody, request, err, apiError) } diff --git a/service/wechatpayopen/pay.partner.transactions.jsapi.go b/service/wechatpayopen/pay.partner.transactions.jsapi.go index 0a44abce..3176eb93 100644 --- a/service/wechatpayopen/pay.partner.transactions.jsapi.go +++ b/service/wechatpayopen/pay.partner.transactions.jsapi.go @@ -28,10 +28,10 @@ func newPayPartnerTransactionsJsapiResult(result PayPartnerTransactionsJsapiResp func (c *Client) PayPartnerTransactionsJsapi(ctx context.Context, notMustParams ...gorequest.Params) *PayPartnerTransactionsJsapiResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("sp_appid", c.config.SpAppid) // 服务商应用ID - params.Set("sp_mchid", c.config.SpMchId) // 服务商户号 - params.Set("sub_appid", c.config.SubAppid) // 子商户应用ID - params.Set("sub_mchid", c.config.SubMchId) // 子商户号 + params.Set("sp_appid", c.GetSpAppid()) // 服务商应用ID + params.Set("sp_mchid", c.GetSpMchId()) // 服务商户号 + params.Set("sub_appid", c.GetSubAppid()) // 子商户应用ID + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 // 请求 request, err := c.request(ctx, apiUrl+"/v3/pay/partner/transactions/jsapi", params, http.MethodPost) if err != nil { diff --git a/service/wechatpayopen/pay.partner.transactions.jsapi.notify.gin.go b/service/wechatpayopen/pay.partner.transactions.jsapi.notify.gin.go new file mode 100644 index 00000000..4a68fffe --- /dev/null +++ b/service/wechatpayopen/pay.partner.transactions.jsapi.notify.gin.go @@ -0,0 +1,89 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/gin-gonic/gin" +) + +// PayPartnerTransactionsJsapiNotifyGinRequest JSAPI下单 - 回调通知 - 请求参数 +type PayPartnerTransactionsJsapiNotifyGinRequest struct { + Id string `form:"id" json:"status" xml:"id" uri:"id" binding:"required"` // 通知ID + CreateTime string `form:"create_time" json:"create_time" xml:"create_time" uri:"create_time" binding:"required"` // 通知创建时间 + EventType string `form:"event_type" json:"event_type" xml:"event_type" uri:"event_type" binding:"required"` // 通知类型 + ResourceType string `form:"resource_type" json:"resource_type" xml:"resource_type" uri:"resource_type" binding:"required"` // 通知数据类型 + Resource struct { + Algorithm string `form:"algorithm" json:"algorithm" xml:"algorithm" uri:"algorithm" binding:"required"` // 加密算法类型 + Ciphertext string `form:"ciphertext" json:"ciphertext" xml:"ciphertext" uri:"ciphertext" binding:"required"` // 数据密文 + AssociatedData string `form:"associated_data" json:"associated_data" xml:"associated_data" uri:"associated_data" binding:"omitempty"` // 附加数据 + OriginalType string `form:"original_type" json:"original_type" xml:"original_type" uri:"original_type" binding:"required"` // 原始类型 + Nonce string `form:"nonce" json:"nonce" xml:"nonce" uri:"nonce" binding:"required"` // 随机串 + } `form:"resource" json:"resource" xml:"resource" uri:"resource" binding:"required"` // 通知数据 + Summary string `form:"summary" json:"summary" xml:"summary" uri:"summary" binding:"required"` // 回调摘要 +} + +// PayPartnerTransactionsJsapiNotifyGin JSAPI下单 - 回调通知 +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_5.shtml +func (c *Client) PayPartnerTransactionsJsapiNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson PayPartnerTransactionsJsapiNotifyGinRequest, response PayPartnerTransactionsJsapiNotifyGinResponse, gcm []byte, err error) { + + // 解析 + err = ginCtx.ShouldBind(&validateJson) + + gcm, err = c.decryptGCM(c.GetApiV3(), validateJson.Resource.Nonce, validateJson.Resource.Ciphertext, validateJson.Resource.AssociatedData) + if err != nil { + return validateJson, response, gcm, err + } + + err = json.Unmarshal(gcm, &response) + + return validateJson, response, gcm, err +} + +// PayPartnerTransactionsJsapiNotifyGinResponse JSAPI下单 - 回调通知 - 解密后数据 +type PayPartnerTransactionsJsapiNotifyGinResponse struct { + SpAppid string `json:"sp_appid"` // 服务商应用ID + SpMchid string `json:"sp_mchid"` // 服务商户号 + SubAppid string `json:"sub_appid,omitempty"` // 子商户应用ID + SubMchid string `json:"sub_mchid"` // 子商户号 + OutTradeNo string `json:"out_trade_no"` // 商户订单号 + TransactionId string `json:"transaction_id"` // 微信支付订单号 + TradeType string `json:"trade_type"` // 交易类型 + TradeState string `json:"trade_state"` // 交易状态 + TradeStateDesc string `json:"trade_state_desc"` // 交易状态描述 + BankType string `json:"bank_type"` // 付款银行 + Attach string `json:"attach,omitempty"` // 附加数据 + SuccessTime string `json:"success_time"` // 支付完成时间 + Payer struct { + Openid string `json:"openid"` // 用户服务标识 + SpOpenid string `json:"sp_openid,omitempty"` // 用户服务标识 + SubOpenid string `json:"sub_openid,omitempty"` // 用户子标识 + } `json:"payer"` // -支付者 + Amount struct { + Total int `json:"total"` // 总金额 + PayerTotal int `json:"payer_total"` // 用户支付金额 + Currency string `json:"currency"` // 货币类型 + PayerCurrency string `json:"payer_currency"` // 用户支付币种 + } `json:"amount"` // 订单金额 + SceneInfo struct { + DeviceId string `json:"device_id,omitempty"` //商户端设备号 + } `json:"scene_info,omitempty"` // 场景信息 + PromotionDetail []struct { + CouponId string `json:"coupon_id"` // 券ID + Name string `json:"name,omitempty"` // 优惠名称 + Scope string `json:"scope,omitempty"` // 优惠范围 + Type string `json:"type,omitempty"` // 优惠类型 + Amount int `json:"amount"` // 优惠券面额 + StockId string `json:"stock_id,omitempty"` // 活动ID + WechatpayContribute int `json:"wechatpay_contribute,omitempty"` // 微信出资 + MerchantContribute int `json:"merchant_contribute,omitempty"` // 商户出资 + OtherContribute int `json:"other_contribute,omitempty"` // 其他出资 + Currency string `json:"currency,omitempty"` // 优惠币种 + GoodsDetail []struct { + GoodsId string `json:"goods_id"` // 商品编码 + Quantity int `json:"quantity"` // 商品数量 + UnitPrice int `json:"unit_price"` // 商品单价 + DiscountAmount int `json:"discount_amount"` // 商品优惠金额 + GoodsRemark string `json:"goods_remark,omitempty"` // 商品备注 + } `json:"goods_detail,omitempty"` // 单品列表 + } `json:"promotion_detail,omitempty"` // 优惠功能 +} diff --git a/service/wechatpayopen/pay.partner.transactions.out-trade-no.close.go b/service/wechatpayopen/pay.partner.transactions.out-trade-no.close.go index 834e3109..ffa6c300 100644 --- a/service/wechatpayopen/pay.partner.transactions.out-trade-no.close.go +++ b/service/wechatpayopen/pay.partner.transactions.out-trade-no.close.go @@ -22,8 +22,8 @@ func newPayPartnerTransactionsOutTradeNoCloseResult(body []byte, http gorequest. func (c *Client) PayPartnerTransactionsOutTradeNoClose(ctx context.Context, outTradeNo string) *PayPartnerTransactionsOutTradeNoCloseResult { // 参数 params := gorequest.NewParams() - params.Set("sp_mchid", c.config.SpMchId) // 服务商户号 - params.Set("sub_mchid", c.config.SubMchId) // 子商户号 + params.Set("sp_mchid", c.GetSpMchId()) // 服务商户号 + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 // 请求 request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/pay/partner/transactions/out-trade-no/%s/close", outTradeNo), params, http.MethodPost) if err != nil { diff --git a/service/wechatpayopen/pay.partner.transactions.out-trade-no.go b/service/wechatpayopen/pay.partner.transactions.out-trade-no.go index 4d416767..8dd8a3eb 100644 --- a/service/wechatpayopen/pay.partner.transactions.out-trade-no.go +++ b/service/wechatpayopen/pay.partner.transactions.out-trade-no.go @@ -73,7 +73,7 @@ func (c *Client) PayPartnerTransactionsOutTradeNo(ctx context.Context, outTradeN // 参数 params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/pay/partner/transactions/out-trade-no/%s?sp_mchid=%s&sub_mchid=%s", outTradeNo, c.config.SpMchId, c.config.SubMchId), params, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf(apiUrl+"/v3/pay/partner/transactions/out-trade-no/%s?sp_mchid=%s&sub_mchid=%s", outTradeNo, c.GetSpMchId(), c.GetSubMchId()), params, http.MethodGet) if err != nil { return newPayPartnerTransactionsOutTradeNoResult(PayPartnerTransactionsOutTradeNoResponse{}, request.ResponseBody, request, err, ApiError{}) } diff --git a/service/wechatpayopen/profitsharing.merchant-configs.go b/service/wechatpayopen/profitsharing.merchant-configs.go new file mode 100644 index 00000000..ed140450 --- /dev/null +++ b/service/wechatpayopen/profitsharing.merchant-configs.go @@ -0,0 +1,44 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingMerchantConfigsResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + MaxRatio int `json:"max_ratio"` // 最大分账比例 +} + +type ProfitSharingMerchantConfigsResult struct { + Result ProfitSharingMerchantConfigsResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingMerchantConfigsResult(result ProfitSharingMerchantConfigsResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingMerchantConfigsResult { + return &ProfitSharingMerchantConfigsResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingMerchantConfigs 查询最大分账比例API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_7.shtml +func (c *Client) ProfitSharingMerchantConfigs(ctx context.Context) *ProfitSharingMerchantConfigsResult { + // 参数 + params := gorequest.NewParams() + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/merchant-configs/"+c.GetSubMchId(), params, http.MethodGet) + if err != nil { + return newProfitSharingMerchantConfigsResult(ProfitSharingMerchantConfigsResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingMerchantConfigsResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingMerchantConfigsResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.orders.go b/service/wechatpayopen/profitsharing.orders.go new file mode 100644 index 00000000..3c469d65 --- /dev/null +++ b/service/wechatpayopen/profitsharing.orders.go @@ -0,0 +1,61 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingOrdersResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + TransactionId string `json:"transaction_id"` // 微信订单号 + OutOrderNo string `json:"out_order_no"` // 商户分账单号 + OrderId string `json:"order_id"` // 微信分账单号 + State string `json:"state"` // 分账单状态 + Receivers []struct { + Amount int `json:"amount"` // 分账金额 + Description string `json:"description"` // 分账描述 + Type string `json:"type"` // 分账接收方类型 + Account string `json:"account"` // 分账接收方账号 + Result string `json:"result"` // 分账结果 + FailReason string `json:"fail_reason"` // 分账失败原因 + DetailId string `json:"detail_id"` // 分账明细单号 + CreateTime string `json:"create_time"` // 分账创建时间 + FinishTime string `json:"finish_time"` // 分账完成时间 + } `json:"receivers,omitempty"` // 分账接收方列表 +} + +type ProfitSharingOrdersResult struct { + Result ProfitSharingOrdersResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingOrdersResult(result ProfitSharingOrdersResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingOrdersResult { + return &ProfitSharingOrdersResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingOrders 请求分账API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_1.shtml +func (c *Client) ProfitSharingOrders(ctx context.Context, notMustParams ...gorequest.Params) *ProfitSharingOrdersResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 + params.Set("appid", c.GetSpAppid()) // 应用ID + params.Set("sub_appid", c.GetSubAppid()) // 子商户应用ID + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/orders", params, http.MethodPost) + if err != nil { + return newProfitSharingOrdersResult(ProfitSharingOrdersResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingOrdersResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingOrdersResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.orders.out_order_no.go b/service/wechatpayopen/profitsharing.orders.out_order_no.go new file mode 100644 index 00000000..5267f5b1 --- /dev/null +++ b/service/wechatpayopen/profitsharing.orders.out_order_no.go @@ -0,0 +1,61 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingOrdersOutOrderNoResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + TransactionId string `json:"transaction_id"` // 微信订单号 + OutOrderNo string `json:"out_order_no"` // 商户分账单号 + OrderId string `json:"order_id"` // 微信分账单号 + State string `json:"state"` // 分账单状态 + Receivers []struct { + Amount int `json:"amount"` // 分账金额 + Description string `json:"description"` // 分账描述 + Type string `json:"type"` // 分账接收方类型 + Account string `json:"account"` // 分账接收方账号 + Result string `json:"result"` // 分账结果 + FailReason string `json:"fail_reason"` // 分账失败原因 + DetailId string `json:"detail_id"` // 分账明细单号 + CreateTime string `json:"create_time"` // 分账创建时间 + FinishTime string `json:"finish_time"` // 分账完成时间 + } `json:"receivers,omitempty"` // 分账接收方列表 +} + +type ProfitSharingOrdersOutOrderNoResult struct { + Result ProfitSharingOrdersOutOrderNoResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingOrdersOutOrderNoResult(result ProfitSharingOrdersOutOrderNoResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingOrdersOutOrderNoResult { + return &ProfitSharingOrdersOutOrderNoResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingOrdersOutOrderNo 查询分账结果API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_2.shtml +func (c *Client) ProfitSharingOrdersOutOrderNo(ctx context.Context, transactionId, outOrderNo string) *ProfitSharingOrdersOutOrderNoResult { + // 参数 + params := gorequest.NewParams() + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 + params.Set("transaction_id", transactionId) // 微信订单号 + params.Set("out_order_no", outOrderNo) // 商户分账单号 + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/orders/"+outOrderNo, params, http.MethodGet) + if err != nil { + return newProfitSharingOrdersOutOrderNoResult(ProfitSharingOrdersOutOrderNoResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingOrdersOutOrderNoResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingOrdersOutOrderNoResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.orders.unfreeze.go b/service/wechatpayopen/profitsharing.orders.unfreeze.go new file mode 100644 index 00000000..721bbd00 --- /dev/null +++ b/service/wechatpayopen/profitsharing.orders.unfreeze.go @@ -0,0 +1,62 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingOrdersUnfreezeResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + TransactionId string `json:"transaction_id"` // 微信订单号 + OutOrderNo string `json:"out_order_no"` // 商户分账单号 + OrderId string `json:"order_id"` // 微信分账单号 + State string `json:"state"` // 分账单状态 + Receivers []struct { + Amount int `json:"amount"` // 分账金额 + Description string `json:"description"` // 分账描述 + Type string `json:"type"` // 分账接收方类型 + Account string `json:"account"` // 分账接收方账号 + Result string `json:"result"` // 分账结果 + FailReason string `json:"fail_reason"` // 分账失败原因 + DetailId string `json:"detail_id"` // 分账明细单号 + CreateTime string `json:"create_time"` // 分账创建时间 + FinishTime string `json:"finish_time"` // 分账完成时间 + } `json:"receivers,omitempty"` // 分账接收方列表 +} + +type ProfitSharingOrdersUnfreezeResult struct { + Result ProfitSharingOrdersUnfreezeResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingOrdersUnfreezeResult(result ProfitSharingOrdersUnfreezeResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingOrdersUnfreezeResult { + return &ProfitSharingOrdersUnfreezeResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingOrdersUnfreeze 解冻剩余资金API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_5.shtml +func (c *Client) ProfitSharingOrdersUnfreeze(ctx context.Context, transactionId, outOrderNo, description string) *ProfitSharingOrdersUnfreezeResult { + // 参数 + params := gorequest.NewParams() + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 + params.Set("transaction_id", transactionId) // 微信订单号 + params.Set("out_order_no", outOrderNo) // 商户分账单号 + params.Set("description", description) // 分账描述 + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/orders/unfreeze", params, http.MethodPost) + if err != nil { + return newProfitSharingOrdersUnfreezeResult(ProfitSharingOrdersUnfreezeResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingOrdersUnfreezeResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingOrdersUnfreezeResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.receivers.add.go b/service/wechatpayopen/profitsharing.receivers.add.go new file mode 100644 index 00000000..ff8b3424 --- /dev/null +++ b/service/wechatpayopen/profitsharing.receivers.add.go @@ -0,0 +1,68 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingReceiversAddResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + Type string `json:"type"` // 分账接收方类型 + Account string `json:"account"` // 分账接收方账号 + Name string `json:"name,omitempty"` // 分账接收方全称 + RelationType string `json:"relation_type"` // 与分账方的关系类型 + CustomRelation string `json:"custom_relation,omitempty"` // 自定义的分账关系 +} + +type ProfitSharingReceiversAddResult struct { + Result ProfitSharingReceiversAddResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingReceiversAddResult(result ProfitSharingReceiversAddResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingReceiversAddResult { + return &ProfitSharingReceiversAddResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingReceiversAdd 添加分账接收方API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_8.shtml +func (c *Client) ProfitSharingReceiversAdd(ctx context.Context, Type, account, name, relationType, customRelation string) *ProfitSharingReceiversAddResult { + // 参数 + params := gorequest.NewParams() + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 + params.Set("appid", c.GetSpAppid()) // 应用ID + params.Set("sub_appid", c.GetSubAppid()) // 子商户应用ID + params.Set("type", Type) // 分账接收方类型 + if Type == MERCHANT_ID { + params.Set("account", account) // 商户号 + params.Set("name", name) // 商户全称 + } + if Type == PERSONAL_OPENID && name != "" { + params.Set("account", account) // 个人openid + params.Set("name", name) // 个人姓名 + } + if Type == PERSONAL_SUB_OPENID && name != "" { + params.Set("account", account) // 个人sub_openid + params.Set("name", name) // 个人姓名 + } + params.Set("relation_type", relationType) // 与分账方的关系类型 + if relationType == "CUSTOM" { + params.Set("custom_relation", customRelation) // 自定义的分账关系 + } + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/receivers/delete", params, http.MethodPost) + if err != nil { + return newProfitSharingReceiversAddResult(ProfitSharingReceiversAddResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingReceiversAddResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingReceiversAddResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.receivers.delete.go b/service/wechatpayopen/profitsharing.receivers.delete.go new file mode 100644 index 00000000..a9e0cce2 --- /dev/null +++ b/service/wechatpayopen/profitsharing.receivers.delete.go @@ -0,0 +1,58 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingReceiversDeleteResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + Type string `json:"type"` // 分账接收方类型 + Account string `json:"account"` // 分账接收方账号 +} + +type ProfitSharingReceiversDeleteResult struct { + Result ProfitSharingReceiversDeleteResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingReceiversDeleteResult(result ProfitSharingReceiversDeleteResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingReceiversDeleteResult { + return &ProfitSharingReceiversDeleteResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingReceiversDelete 删除分账接收方API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_9.shtml +func (c *Client) ProfitSharingReceiversDelete(ctx context.Context, Type, account string) *ProfitSharingReceiversDeleteResult { + // 参数 + params := gorequest.NewParams() + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 + params.Set("appid", c.GetSpAppid()) // 应用ID + params.Set("sub_appid", c.GetSubAppid()) // 子商户应用ID + params.Set("type", Type) // 分账接收方类型 + if Type == MERCHANT_ID { + params.Set("account", account) // 商户号 + } + if Type == PERSONAL_OPENID { + params.Set("account", account) // 个人openid + } + if Type == PERSONAL_SUB_OPENID { + params.Set("account", account) // 个人sub_openid + } + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/receivers/delete", params, http.MethodPost) + if err != nil { + return newProfitSharingReceiversDeleteResult(ProfitSharingReceiversDeleteResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingReceiversDeleteResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingReceiversDeleteResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.receivers.notify.gin.go b/service/wechatpayopen/profitsharing.receivers.notify.gin.go new file mode 100644 index 00000000..70339163 --- /dev/null +++ b/service/wechatpayopen/profitsharing.receivers.notify.gin.go @@ -0,0 +1,56 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/gin-gonic/gin" +) + +// ProfitSharingReceiversNotifyGinRequest 分账动账通知API - 回调通知 - 请求参数 +type ProfitSharingReceiversNotifyGinRequest struct { + Id string `form:"id" json:"status" xml:"id" uri:"id" binding:"required"` // 通知ID + CreateTime string `form:"create_time" json:"create_time" xml:"create_time" uri:"create_time" binding:"required"` // 通知创建时间 + EventType string `form:"event_type" json:"event_type" xml:"event_type" uri:"event_type" binding:"required"` // 通知类型 + Summary string `form:"summary" json:"summary" xml:"summary" uri:"summary" binding:"required"` // 通知简要说明 + ResourceType string `form:"resource_type" json:"resource_type" xml:"resource_type" uri:"resource_type" binding:"required"` // 通知数据类型 + Resource struct { + Algorithm string `form:"algorithm" json:"algorithm" xml:"algorithm" uri:"algorithm" binding:"required"` // 加密算法类型 + Ciphertext string `form:"ciphertext" json:"ciphertext" xml:"ciphertext" uri:"ciphertext" binding:"required"` // 数据密文 + AssociatedData string `form:"associated_data" json:"associated_data" xml:"associated_data" uri:"associated_data" binding:"omitempty"` // 附加数据 + OriginalType string `form:"original_type" json:"original_type" xml:"original_type" uri:"original_type" binding:"required"` // 原始类型 + Nonce string `form:"nonce" json:"nonce" xml:"nonce" uri:"nonce" binding:"required"` // 随机串 + } `form:"resource" json:"resource" xml:"resource" uri:"resource" binding:"required"` // 通知数据 +} + +// ProfitSharingReceiversNotifyGin 分账动账通知API - 回调通知 +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_5.shtml +func (c *Client) ProfitSharingReceiversNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson ProfitSharingReceiversNotifyGinRequest, response ProfitSharingReceiversNotifyGinResponse, gcm []byte, err error) { + + // 解析 + err = ginCtx.ShouldBind(&validateJson) + + gcm, err = c.decryptGCM(c.GetApiV3(), validateJson.Resource.Nonce, validateJson.Resource.Ciphertext, validateJson.Resource.AssociatedData) + if err != nil { + return validateJson, response, gcm, err + } + + err = json.Unmarshal(gcm, &response) + + return validateJson, response, gcm, err +} + +// ProfitSharingReceiversNotifyGinResponse 分账动账通知API - 回调通知 - 解密后数据 +type ProfitSharingReceiversNotifyGinResponse struct { + SpMchid string `json:"sp_mchid"` // 服务商商户号 + SubMchid string `json:"sub_mchid"` // 子商户号 + TransactionId string `json:"transaction_id"` // 微信订单号 + OrderId string `json:"order_id"` // 微信分账/回退单号 + OutOrderNo string `json:"out_order_no"` // 商户分账/回退单号 + Receiver struct { + Type string `json:"type"` // 分账接收方类型 + Account string `json:"account"` // 分账接收方账号 + Amount int `json:"amount"` // 分账动账金额 + Description string `json:"description"` // 分账/回退描述 + } `json:"receiver"` // 分账接收方列表 + SuccessTime string `json:"success_time"` // 成功时间 +} diff --git a/service/wechatpayopen/profitsharing.return-orders.go b/service/wechatpayopen/profitsharing.return-orders.go new file mode 100644 index 00000000..3163a47d --- /dev/null +++ b/service/wechatpayopen/profitsharing.return-orders.go @@ -0,0 +1,55 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingReturnOrdersResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + OrderId string `json:"order_id"` // 微信分账单号 + OutOrderNo string `json:"out_order_no"` // 商户分账单号 + OutReturnNo string `json:"out_return_no"` // 商户回退单号 + ReturnId string `json:"return_id"` // 微信回退单号 + ReturnMchid string `json:"return_mchid"` // 回退商户号 + Amount int `json:"amount"` // 回退金额 + Description string `json:"description"` // 回退描述 + Result string `json:"result"` // 回退结果 + FailReason string `json:"fail_reason"` // 失败原因 + CreateTime string `json:"create_time"` // 创建时间 + FinishTime string `json:"finish_time"` // 完成时间 +} + +type ProfitSharingReturnOrdersResult struct { + Result ProfitSharingReturnOrdersResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingReturnOrdersResult(result ProfitSharingReturnOrdersResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingReturnOrdersResult { + return &ProfitSharingReturnOrdersResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingReturnOrders 请求分账回退API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_3.shtml +func (c *Client) ProfitSharingReturnOrders(ctx context.Context, notMustParams ...gorequest.Params) *ProfitSharingReturnOrdersResult { + // 参数 + params := gorequest.NewParamsWith(notMustParams...) + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/return-orders", params, http.MethodPost) + if err != nil { + return newProfitSharingReturnOrdersResult(ProfitSharingReturnOrdersResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingReturnOrdersResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingReturnOrdersResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.return-orders.out_return_no.go b/service/wechatpayopen/profitsharing.return-orders.out_return_no.go new file mode 100644 index 00000000..dce69abb --- /dev/null +++ b/service/wechatpayopen/profitsharing.return-orders.out_return_no.go @@ -0,0 +1,57 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingReturnOrdersOutReturnNoResponse struct { + SubMchid string `json:"sub_mchid"` // 子商户号 + OrderId string `json:"order_id"` // 微信分账单号 + OutOrderNo string `json:"out_order_no"` // 商户分账单号 + OutReturnNo string `json:"out_return_no"` // 商户回退单号 + ReturnId string `json:"return_id"` // 微信回退单号 + ReturnMchid string `json:"return_mchid"` // 回退商户号 + Amount int `json:"amount"` // 回退金额 + Description string `json:"description"` // 回退描述 + Result string `json:"result"` // 回退结果 + FailReason string `json:"fail_reason"` // 失败原因 + CreateTime string `json:"create_time"` // 创建时间 + FinishTime string `json:"finish_time"` // 完成时间 +} + +type ProfitSharingReturnOrdersOutReturnNoResult struct { + Result ProfitSharingReturnOrdersOutReturnNoResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingReturnOrdersOutReturnNoResult(result ProfitSharingReturnOrdersOutReturnNoResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingReturnOrdersOutReturnNoResult { + return &ProfitSharingReturnOrdersOutReturnNoResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingReturnOrdersOutReturnNo 查询分账回退结果API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_4.shtml +func (c *Client) ProfitSharingReturnOrdersOutReturnNo(ctx context.Context, outReturnNo, outOrderNo string) *ProfitSharingReturnOrdersOutReturnNoResult { + // 参数 + params := gorequest.NewParams() + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 + params.Set("out_return_no", outReturnNo) // 商户回退单号 + params.Set("out_order_no", outOrderNo) // 商户分账单号 + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/return-orders/"+outReturnNo, params, http.MethodGet) + if err != nil { + return newProfitSharingReturnOrdersOutReturnNoResult(ProfitSharingReturnOrdersOutReturnNoResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingReturnOrdersOutReturnNoResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingReturnOrdersOutReturnNoResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/profitsharing.transactions.amounts.go b/service/wechatpayopen/profitsharing.transactions.amounts.go new file mode 100644 index 00000000..ef4dad4e --- /dev/null +++ b/service/wechatpayopen/profitsharing.transactions.amounts.go @@ -0,0 +1,44 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/dtapps/go-library/utils/gorequest" + "net/http" +) + +type ProfitSharingTransactionsAmountsResponse struct { + TransactionId string `json:"transaction_id"` // 微信订单号 + UnsplitAmount int `json:"unsplit_amount"` // 订单剩余待分金额 +} + +type ProfitSharingTransactionsAmountsResult struct { + Result ProfitSharingTransactionsAmountsResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 +} + +func newProfitSharingTransactionsAmountsResult(result ProfitSharingTransactionsAmountsResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *ProfitSharingTransactionsAmountsResult { + return &ProfitSharingTransactionsAmountsResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} +} + +// ProfitSharingTransactionsAmounts 查询剩余待分金额API +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_6.shtml +func (c *Client) ProfitSharingTransactionsAmounts(ctx context.Context, transactionId string) *ProfitSharingTransactionsAmountsResult { + // 参数 + params := gorequest.NewParams() + // 请求 + request, err := c.request(ctx, apiUrl+"/v3/profitsharing/transactions/"+transactionId, params, http.MethodGet) + if err != nil { + return newProfitSharingTransactionsAmountsResult(ProfitSharingTransactionsAmountsResponse{}, request.ResponseBody, request, err, ApiError{}) + } + // 定义 + var response ProfitSharingTransactionsAmountsResponse + err = json.Unmarshal(request.ResponseBody, &response) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newProfitSharingTransactionsAmountsResult(response, request.ResponseBody, request, err, apiError) +} diff --git a/service/wechatpayopen/refund.domestic.refunds.go b/service/wechatpayopen/refund.domestic.refunds.go index a91ae6aa..fedc646d 100644 --- a/service/wechatpayopen/refund.domestic.refunds.go +++ b/service/wechatpayopen/refund.domestic.refunds.go @@ -51,14 +51,15 @@ type RefundDomesticRefundsResponse struct { } type RefundDomesticRefundsResult struct { - Result RefundDomesticRefundsResponse // 结果 - Body []byte // 内容 - Http gorequest.Response // 请求 - Err error // 错误 + Result RefundDomesticRefundsResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 } -func newRefundDomesticRefundsResult(result RefundDomesticRefundsResponse, body []byte, http gorequest.Response, err error) *RefundDomesticRefundsResult { - return &RefundDomesticRefundsResult{Result: result, Body: body, Http: http, Err: err} +func newRefundDomesticRefundsResult(result RefundDomesticRefundsResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *RefundDomesticRefundsResult { + return &RefundDomesticRefundsResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} } // RefundDomesticRefunds 申请退款API @@ -66,14 +67,17 @@ func newRefundDomesticRefundsResult(result RefundDomesticRefundsResponse, body [ func (c *Client) RefundDomesticRefunds(ctx context.Context, notMustParams ...gorequest.Params) *RefundDomesticRefundsResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("sub_mchid", c.config.SubMchId) // 子商户号 + params.Set("sub_mchid", c.GetSubMchId()) // 子商户号 // 请求 request, err := c.request(ctx, apiUrl+"/v3/refund/domestic/refunds", params, http.MethodPost) if err != nil { - return newRefundDomesticRefundsResult(RefundDomesticRefundsResponse{}, request.ResponseBody, request, err) + return newRefundDomesticRefundsResult(RefundDomesticRefundsResponse{}, request.ResponseBody, request, err, ApiError{}) } // 定义 var response RefundDomesticRefundsResponse err = json.Unmarshal(request.ResponseBody, &response) - return newRefundDomesticRefundsResult(response, request.ResponseBody, request, err) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newRefundDomesticRefundsResult(response, request.ResponseBody, request, err, apiError) } diff --git a/service/wechatpayopen/refund.domestic.refunds.notify.gin.go b/service/wechatpayopen/refund.domestic.refunds.notify.gin.go new file mode 100644 index 00000000..25138728 --- /dev/null +++ b/service/wechatpayopen/refund.domestic.refunds.notify.gin.go @@ -0,0 +1,59 @@ +package wechatpayopen + +import ( + "context" + "encoding/json" + "github.com/gin-gonic/gin" +) + +// RefundDomesticRefundsNoNotifyGinRequest 申请退款API - 回调通知 - 请求参数 +type RefundDomesticRefundsNoNotifyGinRequest struct { + Id string `form:"id" json:"status" xml:"id" uri:"id" binding:"required"` // 通知ID + CreateTime string `form:"create_time" json:"create_time" xml:"create_time" uri:"create_time" binding:"required"` // 通知创建时间 + EventType string `form:"event_type" json:"event_type" xml:"event_type" uri:"event_type" binding:"required"` // 通知类型 + Summary string `form:"summary" json:"summary" xml:"summary" uri:"summary" binding:"required"` // 通知简要说明 + ResourceType string `form:"resource_type" json:"resource_type" xml:"resource_type" uri:"resource_type" binding:"required"` // 通知数据类型 + Resource struct { + Algorithm string `form:"algorithm" json:"algorithm" xml:"algorithm" uri:"algorithm" binding:"required"` // 加密算法类型 + Ciphertext string `form:"ciphertext" json:"ciphertext" xml:"ciphertext" uri:"ciphertext" binding:"required"` // 数据密文 + AssociatedData string `form:"associated_data" json:"associated_data" xml:"associated_data" uri:"associated_data" binding:"omitempty"` // 附加数据 + OriginalType string `form:"original_type" json:"original_type" xml:"original_type" uri:"original_type" binding:"required"` // 原始类型 + Nonce string `form:"nonce" json:"nonce" xml:"nonce" uri:"nonce" binding:"required"` // 随机串 + } `form:"resource" json:"resource" xml:"resource" uri:"resource" binding:"required"` // 通知数据 +} + +// RefundDomesticRefundsNoNotifyGin 申请退款API - 回调通知 +// https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_11.shtml +func (c *Client) RefundDomesticRefundsNoNotifyGin(ctx context.Context, ginCtx *gin.Context) (validateJson RefundDomesticRefundsNoNotifyGinRequest, response RefundDomesticRefundsNoNotifyGinResponse, gcm []byte, err error) { + + // 解析 + err = ginCtx.ShouldBind(&validateJson) + + gcm, err = c.decryptGCM(c.GetApiV3(), validateJson.Resource.Nonce, validateJson.Resource.Ciphertext, validateJson.Resource.AssociatedData) + if err != nil { + return validateJson, response, gcm, err + } + + err = json.Unmarshal(gcm, &response) + + return validateJson, response, gcm, err +} + +// RefundDomesticRefundsNoNotifyGinResponse 申请退款API - 回调通知 - 解密后数据 +type RefundDomesticRefundsNoNotifyGinResponse struct { + SpMchid string `json:"sp_mchid"` // 服务商户号 + SubMchid string `json:"sub_mchid"` // 子商户号 + OutTradeNo string `json:"out_trade_no"` // 商户订单号 + TransactionId string `json:"transaction_id"` // 微信支付订单号 + OutRefundNo string `json:"out_refund_no"` // 商户退款单号 + RefundId string `json:"refund_id"` // 微信支付退款单号 + RefundStatus string `json:"refund_status"` // 退款状态 + SuccessTime string `json:"success_time"` // 退款成功时间 + UserReceivedAccount string `json:"user_received_account"` // 退款入账账户 + Amount struct { + Total int `json:"total"` // 订单金额 + Refund int `json:"refund"` // 退款金额 + PayerTotal int `json:"payer_total"` // 用户支付金额 + PayerRefund int `json:"payer_refund"` // 用户退款金额 + } `json:"amount"` // 金额信息 +} diff --git a/service/wechatpayopen/refund.domestic.refunds.out_refund_no.go b/service/wechatpayopen/refund.domestic.refunds.out_refund_no.go index 26ca6ae2..dbf166ee 100644 --- a/service/wechatpayopen/refund.domestic.refunds.out_refund_no.go +++ b/service/wechatpayopen/refund.domestic.refunds.out_refund_no.go @@ -51,14 +51,15 @@ type RefundDomesticRefundsOutRefundNoResponse struct { } type RefundDomesticRefundsOutRefundNoResult struct { - Result RefundDomesticRefundsOutRefundNoResponse // 结果 - Body []byte // 内容 - Http gorequest.Response // 请求 - Err error // 错误 + Result RefundDomesticRefundsOutRefundNoResponse // 结果 + Body []byte // 内容 + Http gorequest.Response // 请求 + Err error // 错误 + ApiError ApiError // 接口错误 } -func newRefundDomesticRefundsOutRefundNoResult(result RefundDomesticRefundsOutRefundNoResponse, body []byte, http gorequest.Response, err error) *RefundDomesticRefundsOutRefundNoResult { - return &RefundDomesticRefundsOutRefundNoResult{Result: result, Body: body, Http: http, Err: err} +func newRefundDomesticRefundsOutRefundNoResult(result RefundDomesticRefundsOutRefundNoResponse, body []byte, http gorequest.Response, err error, apiError ApiError) *RefundDomesticRefundsOutRefundNoResult { + return &RefundDomesticRefundsOutRefundNoResult{Result: result, Body: body, Http: http, Err: err, ApiError: apiError} } // RefundDomesticRefundsOutRefundNo 查询单笔退款API @@ -67,12 +68,15 @@ func (c *Client) RefundDomesticRefundsOutRefundNo(ctx context.Context, outRefund // 参数 params := gorequest.NewParams() // 请求 - request, err := c.request(ctx, apiUrl+"/v3/refund/domestic/refunds/"+outRefundNo+"?sub_mchid="+c.config.SubMchId, params, http.MethodGet) + request, err := c.request(ctx, apiUrl+"/v3/refund/domestic/refunds/"+outRefundNo+"?sub_mchid="+c.GetSubMchId(), params, http.MethodGet) if err != nil { - return newRefundDomesticRefundsOutRefundNoResult(RefundDomesticRefundsOutRefundNoResponse{}, request.ResponseBody, request, err) + return newRefundDomesticRefundsOutRefundNoResult(RefundDomesticRefundsOutRefundNoResponse{}, request.ResponseBody, request, err, ApiError{}) } // 定义 var response RefundDomesticRefundsOutRefundNoResponse err = json.Unmarshal(request.ResponseBody, &response) - return newRefundDomesticRefundsOutRefundNoResult(response, request.ResponseBody, request, err) + // 错误 + var apiError ApiError + err = json.Unmarshal(request.ResponseBody, &apiError) + return newRefundDomesticRefundsOutRefundNoResult(response, request.ResponseBody, request, err, apiError) } diff --git a/service/wechatpayopen/request.go b/service/wechatpayopen/request.go index 338965ab..903d4d26 100644 --- a/service/wechatpayopen/request.go +++ b/service/wechatpayopen/request.go @@ -15,7 +15,7 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte } // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -29,6 +29,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置参数 client.SetParams(params) + // 设置用户代理 + client.SetUserAgent(gorequest.GetRandomUserAgentSystem()) + // 设置头部 client.SetHeader("Authorization", authorization) client.SetHeader("Accept", "application/json") @@ -40,13 +43,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } - return request, err } diff --git a/service/wechatpayopen/set.go b/service/wechatpayopen/set.go index f80df112..b8193f8a 100644 --- a/service/wechatpayopen/set.go +++ b/service/wechatpayopen/set.go @@ -2,7 +2,7 @@ package wechatpayopen // SubConfig 子商户配置 func (c *Client) SubConfig(subAppid, subMchId string) *Client { - c.config.SubAppid = subAppid - c.config.SubMchId = subMchId + c.config.subAppid = subAppid + c.config.subMchId = subMchId return c } diff --git a/service/wechatpayopen/sign.decrypt.go b/service/wechatpayopen/sign.decrypt.go new file mode 100644 index 00000000..d5e3dffa --- /dev/null +++ b/service/wechatpayopen/sign.decrypt.go @@ -0,0 +1,5 @@ +package wechatpayopen + +func (c *Client) SignDecrypt(aesKey, associatedData, nonce, ciphertext string) ([]byte, error) { + return c.decryptGCM(aesKey, nonce, ciphertext, associatedData) +} diff --git a/service/wechatpayopen/sign.go b/service/wechatpayopen/sign.go index 70cdce3a..42ed4817 100644 --- a/service/wechatpayopen/sign.go +++ b/service/wechatpayopen/sign.go @@ -86,7 +86,7 @@ func (c *Client) authorization(method string, paramMap map[string]interface{}, r // 构造签名串 message := fmt.Sprintf(SignatureMessageFormat, method, canonicalUrl, timestamp, nonce, signBody) - sign, err := c.signSHA256WithRSA(message, c.getRsa([]byte(c.config.MchSslKey))) + sign, err := c.signSHA256WithRSA(message, c.getRsa([]byte(c.GetMchSslKey()))) if err != nil { return token, err @@ -94,7 +94,7 @@ func (c *Client) authorization(method string, paramMap map[string]interface{}, r authorization := fmt.Sprintf( HeaderAuthorizationFormat, getAuthorizationType(), - c.config.SpMchId, nonce, timestamp, c.config.MchSslSerialNo, sign, + c.GetSpMchId(), nonce, timestamp, c.GetMchSslSerialNo(), sign, ) return authorization, nil diff --git a/service/wechatqy/client.go b/service/wechatqy/client.go index 255e7ce3..ca80fd07 100644 --- a/service/wechatqy/client.go +++ b/service/wechatqy/client.go @@ -1,55 +1,47 @@ package wechatqy import ( - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppId string - AgentId int - Secret string - RedirectUri string - Key string // key - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string + AgentId int + Secret string + RedirectUri string + Key string // key } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appId string + agentId int + secret string + redirectUri string + key string + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appId = config.AppId + c.config.agentId = config.AgentId + c.config.secret = config.Secret + c.config.redirectUri = config.RedirectUri + c.config.key = config.Key - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/wechatqy/config.go b/service/wechatqy/config.go new file mode 100644 index 00000000..55b3fbd7 --- /dev/null +++ b/service/wechatqy/config.go @@ -0,0 +1,17 @@ +package wechatqy + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) Config(key string) *Client { + c.config.key = key + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatqy/const.go b/service/wechatqy/const.go index 18e402a6..f26ec4fc 100644 --- a/service/wechatqy/const.go +++ b/service/wechatqy/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "wechatqy" + LogTable = "wechatqy" ) diff --git a/service/wechatqy/get.go b/service/wechatqy/get.go index 9982fa30..54b23982 100644 --- a/service/wechatqy/get.go +++ b/service/wechatqy/get.go @@ -1,21 +1,27 @@ package wechatqy +import "github.com/dtapps/go-library/utils/golog" + func (c *Client) GetKey() string { - return c.config.Key + return c.config.key } func (c *Client) GetAppId() string { - return c.config.AppId + return c.config.appId } func (c *Client) GetAgentId() int { - return c.config.AgentId + return c.config.agentId } func (c *Client) GetSecret() string { - return c.config.Secret + return c.config.secret } func (c *Client) GetRedirectUri() string { - return c.config.RedirectUri + return c.config.redirectUri +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/wechatqy/request.go b/service/wechatqy/request.go index 6046cc38..d7c70b6c 100644 --- a/service/wechatqy/request.go +++ b/service/wechatqy/request.go @@ -8,7 +8,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -22,18 +22,18 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置参数 client.SetParams(params) + // 传入SDk版本 + client.AfferentSdkUserVersion(go_library.Version()) + // 发起请求 request, err := client.Request(ctx) if err != nil { return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/wechatunion/cgi-bin.token.monitor.go b/service/wechatunion/cgi-bin.token.monitor.go index 5e5ea834..609e0c0f 100644 --- a/service/wechatunion/cgi-bin.token.monitor.go +++ b/service/wechatunion/cgi-bin.token.monitor.go @@ -7,14 +7,14 @@ import ( ) func (c *Client) GetAccessTokenMonitor(ctx context.Context) (string, error) { - if c.config.RedisClient.Db == nil { + if c.cache.redisClient.Db == nil { return "", errors.New("驱动没有初始化") } result := c.GetCallBackIp(ctx) if len(result.Result.IpList) <= 0 { token := c.CgiBinToken(ctx) - c.config.RedisClient.Set(ctx, c.getAccessTokenCacheKeyName(), token.Result.AccessToken, time.Second*7000) + c.cache.redisClient.Set(ctx, c.getAccessTokenCacheKeyName(), token.Result.AccessToken, time.Second*7000) return token.Result.AccessToken, nil } - return c.config.AccessToken, nil + return c.config.accessToken, nil } diff --git a/service/wechatunion/cgi-bin.token.rdb.go b/service/wechatunion/cgi-bin.token.rdb.go index 279cf717..d36d5d9b 100644 --- a/service/wechatunion/cgi-bin.token.rdb.go +++ b/service/wechatunion/cgi-bin.token.rdb.go @@ -2,22 +2,21 @@ package wechatunion import ( "context" - "fmt" "time" ) func (c *Client) GetAccessToken(ctx context.Context) string { - if c.config.RedisClient.Db == nil { - return c.config.AccessToken + if c.cache.redisClient.Db == nil { + return c.config.accessToken } - newCache := c.config.RedisClient.NewSimpleStringCache(c.config.RedisClient.NewStringOperation(), time.Second*7000) + newCache := c.cache.redisClient.NewSimpleStringCache(c.cache.redisClient.NewStringOperation(), time.Second*7000) newCache.DBGetter = func() string { token := c.CgiBinToken(ctx) return token.Result.AccessToken } - return newCache.GetCache(c.getAccessTokenCacheKeyName()) + return newCache.GetCache(ctx, c.getAccessTokenCacheKeyName()) } func (c *Client) getAccessTokenCacheKeyName() string { - return fmt.Sprintf("wechat_access_token:%v", c.getAppId()) + return c.cache.wechatAccessTokenPrefix + c.GetAppId() } diff --git a/service/wechatunion/cgi_bin.token.go b/service/wechatunion/cgi_bin.token.go index 4e8a3604..81ae88ac 100644 --- a/service/wechatunion/cgi_bin.token.go +++ b/service/wechatunion/cgi_bin.token.go @@ -31,7 +31,7 @@ func newCgiBinTokenResult(result CgiBinTokenResponse, byte []byte, http goreques // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html func (c *Client) CgiBinToken(ctx context.Context) *CgiBinTokenResult { // 请求 - request, err := c.request(ctx, fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", c.getAppId(), c.getAppSecret()), map[string]interface{}{}, http.MethodGet) + request, err := c.request(ctx, fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", c.GetAppId(), c.GetAppSecret()), map[string]interface{}{}, http.MethodGet) // 定义 var response CgiBinTokenResponse err = json.Unmarshal(request.ResponseBody, &response) diff --git a/service/wechatunion/client.go b/service/wechatunion/client.go index 6ef8a877..d6246c37 100644 --- a/service/wechatunion/client.go +++ b/service/wechatunion/client.go @@ -4,52 +4,56 @@ import ( "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - AppId string // 小程序唯一凭证,即 appId - AppSecret string // 小程序唯一凭证密钥,即 appSecret - AccessToken string // 接口调用凭证 - Pid string // 推广位PID - RedisClient *dorm.RedisClient // 缓存数据库 - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// 缓存前缀 +// wechat_union:wechat_access_token: +type redisCachePrefixFun func() (wechatAccessToken string) + +// ClientConfig 实例配置 +type ClientConfig struct { + AppId string // 小程序唯一凭证,即 appId + AppSecret string // 小程序唯一凭证密钥,即 appSecret + Pid string // 推广位PID + RedisClient *dorm.RedisClient // 缓存数据库 + RedisCachePrefixFun redisCachePrefixFun // 缓存前缀 } -// Client 微信小程序联盟 +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + appId string // 小程序唯一凭证,即 appId + appSecret string // 小程序唯一凭证密钥,即 appSecret + accessToken string // 接口调用凭证 + pid string // 推广位PID + } + cache struct { + redisClient *dorm.RedisClient // 缓存数据库 + wechatAccessTokenPrefix string // AccessToken + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.appId = config.AppId + c.config.appSecret = config.AppSecret + c.config.pid = config.Pid - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } + c.requestClient = gorequest.NewHttp() + + c.cache.redisClient = config.RedisClient + + c.cache.wechatAccessTokenPrefix = config.RedisCachePrefixFun() + if c.cache.wechatAccessTokenPrefix == "" { + return nil, redisCachePrefixNoConfig } return c, nil diff --git a/service/wechatunion/config.go b/service/wechatunion/config.go new file mode 100644 index 00000000..24def2c3 --- /dev/null +++ b/service/wechatunion/config.go @@ -0,0 +1,25 @@ +package wechatunion + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApp 配置 +func (c *Client) ConfigApp(appId, appSecret string) *Client { + c.config.appId = appId + c.config.appSecret = appSecret + return c +} + +// ConfigPid 配置 +func (c *Client) ConfigPid(pid string) *Client { + c.config.pid = pid + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wechatunion/const.go b/service/wechatunion/const.go index 8af75a01..f2c12bec 100644 --- a/service/wechatunion/const.go +++ b/service/wechatunion/const.go @@ -5,5 +5,5 @@ const ( ) const ( - logTable = "wechatunion" + LogTable = "wechatunion" ) diff --git a/service/wechatunion/error.go b/service/wechatunion/error.go new file mode 100644 index 00000000..6d72e760 --- /dev/null +++ b/service/wechatunion/error.go @@ -0,0 +1,7 @@ +package wechatunion + +import "errors" + +var ( + redisCachePrefixNoConfig = errors.New("请配置 RedisCachePrefix") +) diff --git a/service/wechatunion/get.go b/service/wechatunion/get.go index cb9d9386..4c7e802a 100644 --- a/service/wechatunion/get.go +++ b/service/wechatunion/get.go @@ -1,20 +1,27 @@ package wechatunion -import "context" +import ( + "context" + "github.com/dtapps/go-library/utils/golog" +) -func (c *Client) getAppId() string { - return c.config.AppId +func (c *Client) GetAppId() string { + return c.config.appId } -func (c *Client) getAppSecret() string { - return c.config.AppSecret +func (c *Client) GetAppSecret() string { + return c.config.appSecret +} + +func (c *Client) GetPid() string { + return c.config.pid } func (c *Client) getAccessToken(ctx context.Context) string { - c.config.AccessToken = c.GetAccessToken(ctx) - return c.config.AccessToken + c.config.accessToken = c.GetAccessToken(ctx) + return c.config.accessToken } -func (c *Client) getPid() string { - return c.config.Pid +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client } diff --git a/service/wechatunion/promoter.product.generate.go b/service/wechatunion/promoter.product.generate.go index 4d8d0c45..8aa6b359 100644 --- a/service/wechatunion/promoter.product.generate.go +++ b/service/wechatunion/promoter.product.generate.go @@ -59,7 +59,7 @@ func newPromoterProductGenerateResult(result PromoterProductGenerateResponse, bo func (c *Client) PromoterProductGenerate(ctx context.Context, notMustParams ...gorequest.Params) *PromoterProductGenerateResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("pid", c.getPid()) + params.Set("pid", c.GetPid()) // 请求 request, err := c.request(ctx, apiUrl+fmt.Sprintf("/promoter/product/generate?access_token=%s", c.getAccessToken(ctx)), params, http.MethodPost) // 定义 diff --git a/service/wechatunion/request.go b/service/wechatunion/request.go index 5da1d4e3..5f95b390 100644 --- a/service/wechatunion/request.go +++ b/service/wechatunion/request.go @@ -10,7 +10,7 @@ import ( func (c *Client) request(ctx context.Context, url string, params map[string]interface{}, method string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) @@ -30,12 +30,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/weishi/client.go b/service/weishi/client.go index b9345d86..04363267 100644 --- a/service/weishi/client.go +++ b/service/weishi/client.go @@ -2,55 +2,36 @@ package weishi import ( "errors" - "github.com/dtapps/go-library/utils/dorm" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" "net/http" "strings" ) -type ConfigClient struct { - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { } +// Client 实例 type Client struct { - ua string // 用户代理 - client *gorequest.App // 请求客户端 - log *golog.ApiClient // 日志服务 - config *ConfigClient // 配置 + requestClient *gorequest.App // 请求服务 + config struct { + ua string // 用户代理 + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1" + c.config.ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1" - c.client = gorequest.NewHttp() - - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/weishi/config.go b/service/weishi/config.go new file mode 100644 index 00000000..b3881afc --- /dev/null +++ b/service/weishi/config.go @@ -0,0 +1,12 @@ +package weishi + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/weishi/const.go b/service/weishi/const.go index 15e197be..d3165722 100644 --- a/service/weishi/const.go +++ b/service/weishi/const.go @@ -1,5 +1,5 @@ package weishi const ( - logTable = "weishi" + LogTable = "weishi" ) diff --git a/service/weishi/get.go b/service/weishi/get.go new file mode 100644 index 00000000..d546fa04 --- /dev/null +++ b/service/weishi/get.go @@ -0,0 +1,7 @@ +package weishi + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/weishi/request.go b/service/weishi/request.go index 485fa68a..586ab37f 100644 --- a/service/weishi/request.go +++ b/service/weishi/request.go @@ -9,13 +9,13 @@ import ( func (c *Client) request(ctx context.Context, url string) (gorequest.Response, error) { // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 client.SetUri(url) // 设置用户代理 - client.SetUserAgent(c.ua) + client.SetUserAgent(c.config.ua) // 发起请求 request, err := client.Get(ctx) @@ -23,12 +23,9 @@ func (c *Client) request(ctx context.Context, url string) (gorequest.Response, e return gorequest.Response{}, err } - // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + // 记录日志 + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/wikeyun/client.go b/service/wikeyun/client.go index 2bdc30ec..56d051b4 100644 --- a/service/wikeyun/client.go +++ b/service/wikeyun/client.go @@ -1,61 +1,45 @@ package wikeyun import ( - "context" - "github.com/dtapps/go-library/utils/dorm" - "github.com/dtapps/go-library/utils/goip" "github.com/dtapps/go-library/utils/golog" "github.com/dtapps/go-library/utils/gorequest" - "gorm.io/gorm" ) -type ConfigClient struct { - StoreId int // 店铺ID - AppKey int // key - AppSecret string // secret - MongoDb *dorm.MongoClient // 日志数据库 - PgsqlDb *gorm.DB // 日志数据库 - DatabaseName string // 库名 +// ClientConfig 实例配置 +type ClientConfig struct { + StoreId int // 店铺ID + AppKey int // key + AppSecret string // secret + CurrentIp string // 当前ip } +// Client 实例 type Client struct { - client *gorequest.App // 请求客户端 - clientIp string // Ip - log *golog.ApiClient // 日志服务 - config *ConfigClient + requestClient *gorequest.App // 请求服务 + config struct { + clientIp string // 当前Ip + storeId int // 店铺ID + appKey int // key + appSecret string // secret + } + log struct { + status bool // 状态 + client *golog.ApiClient // 日志服务 + } } -func NewClient(config *ConfigClient) (*Client, error) { +// NewClient 创建实例化 +func NewClient(config *ClientConfig) (*Client, error) { - var err error - c := &Client{config: config} + c := &Client{} - c.client = gorequest.NewHttp() + c.config.clientIp = config.CurrentIp - if c.config.PgsqlDb != nil { - c.log, err = golog.NewApiClient( - golog.WithGormClient(c.config.PgsqlDb), - golog.WithTableName(logTable), - ) - if err != nil { - return nil, err - } - } - if c.config.MongoDb != nil { - c.log, err = golog.NewApiClient( - golog.WithMongoClient(c.config.MongoDb), - golog.WithDatabaseName(c.config.DatabaseName), - golog.WithCollectionName(logTable), - ) - if err != nil { - return nil, err - } - } + c.config.storeId = config.StoreId + c.config.appKey = config.AppKey + c.config.appSecret = config.AppSecret - xip := goip.GetOutsideIp(context.Background()) - if xip != "" && xip != "0.0.0.0" { - c.clientIp = xip - } + c.requestClient = gorequest.NewHttp() return c, nil } diff --git a/service/wikeyun/config.go b/service/wikeyun/config.go new file mode 100644 index 00000000..60f0460b --- /dev/null +++ b/service/wikeyun/config.go @@ -0,0 +1,20 @@ +package wikeyun + +import "github.com/dtapps/go-library/utils/golog" + +// ConfigApp 配置 +func (c *Client) ConfigApp(storeId, appKey int, appSecret string) *Client { + c.config.storeId = storeId + c.config.appKey = appKey + c.config.appSecret = appSecret + return c +} + +// ConfigApiClientFun 日志配置 +func (c *Client) ConfigApiClientFun(apiClientFun golog.ApiClientFun) { + apiClient := apiClientFun() + if apiClient != nil { + c.log.client = apiClient + c.log.status = true + } +} diff --git a/service/wikeyun/const.go b/service/wikeyun/const.go index e939b1c4..8c3ad3fc 100644 --- a/service/wikeyun/const.go +++ b/service/wikeyun/const.go @@ -9,5 +9,5 @@ const ( ) const ( - logTable = "wikeyun" + LogTable = "wikeyun" ) diff --git a/service/wikeyun/get.go b/service/wikeyun/get.go new file mode 100644 index 00000000..6138c3f3 --- /dev/null +++ b/service/wikeyun/get.go @@ -0,0 +1,23 @@ +package wikeyun + +import "github.com/dtapps/go-library/utils/golog" + +func (c *Client) GetStoreId() int { + return c.config.storeId +} + +func (c *Client) GetAppKey() int { + return c.config.appKey +} + +func (c *Client) GetAppSecret() string { + return c.config.appSecret +} + +func (c *Client) GetClientIp() string { + return c.config.clientIp +} + +func (c *Client) GetLog() *golog.ApiClient { + return c.log.client +} diff --git a/service/wikeyun/request.go b/service/wikeyun/request.go index 76e0b150..5235c8f9 100644 --- a/service/wikeyun/request.go +++ b/service/wikeyun/request.go @@ -14,10 +14,10 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte sign := c.sign(params) // 创建请求 - client := c.client + client := c.requestClient // 设置请求地址 - client.SetUri(fmt.Sprintf("%s?app_key=%d×tamp=%s&client=%s&format=%s&v=%s&sign=%s", url, c.config.AppKey, sign.Timestamp, sign.Client, sign.Format, sign.V, sign.Sign)) + client.SetUri(fmt.Sprintf("%s?app_key=%d×tamp=%s&client=%s&format=%s&v=%s&sign=%s", url, c.GetAppKey(), sign.Timestamp, sign.Client, sign.Format, sign.V, sign.Sign)) // 设置FORM格式 client.SetContentTypeForm() @@ -25,6 +25,9 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte // 设置参数 client.SetParams(params) + // 传入SDk版本 + client.AfferentSdkUserVersion(go_library.Version()) + // 发起请求 request, err := client.Post(ctx) if err != nil { @@ -32,11 +35,8 @@ func (c *Client) request(ctx context.Context, url string, params map[string]inte } // 日志 - if c.config.PgsqlDb != nil { - go c.log.GormMiddleware(ctx, request, go_library.Version()) - } - if c.config.MongoDb != nil { - go c.log.MongoMiddleware(ctx, request, go_library.Version()) + if c.log.status { + go c.log.client.Middleware(ctx, request, go_library.Version()) } return request, err diff --git a/service/wikeyun/rest.power.add_card.go b/service/wikeyun/rest.power.add_card.go index c561c885..910f609e 100644 --- a/service/wikeyun/rest.power.add_card.go +++ b/service/wikeyun/rest.power.add_card.go @@ -38,7 +38,7 @@ func newRestPowerAddCardResult(result RestPowerAddCardResponse, body []byte, htt func (c *Client) RestPowerAddCard(ctx context.Context, notMustParams ...gorequest.Params) *RestPowerAddCardResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("store_id", c.config.StoreId) // 店铺ID + params.Set("store_id", c.GetStoreId()) // 店铺ID // 请求 request, err := c.request(ctx, apiUrl+"/rest/Power/addCard", params) // 定义 diff --git a/service/wikeyun/rest.power.push_order.go b/service/wikeyun/rest.power.push_order.go index e9fbbc79..f31a1078 100644 --- a/service/wikeyun/rest.power.push_order.go +++ b/service/wikeyun/rest.power.push_order.go @@ -31,7 +31,7 @@ func newRestPowerPushOrderResult(result RestPowerPushOrderResponse, body []byte, func (c *Client) RestPowerPushOrder(ctx context.Context, notMustParams ...gorequest.Params) *RestPowerPushOrderResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("store_id", c.config.StoreId) // 店铺ID + params.Set("store_id", c.GetStoreId()) // 店铺ID // 请求 request, err := c.request(ctx, apiUrl+"/rest/Power/pushOrder", params) // 定义 diff --git a/service/wikeyun/rest.power.push_order.notify.gin.go b/service/wikeyun/rest.power.push_order.notify.gin.go new file mode 100644 index 00000000..2575b98b --- /dev/null +++ b/service/wikeyun/rest.power.push_order.notify.gin.go @@ -0,0 +1,40 @@ +package wikeyun + +import ( + "context" + "github.com/gin-gonic/gin" +) + +type ResponseRestPowerPushOrderNotifyGin struct { + Status int `form:"status" json:"status" xml:"status" uri:"status" binding:"omitempty"` // 状态 订单状态 0 待支付 1 已付 充值中 2充值成功 3充值失败 需要退款 4退款成功 5已超时 6待充值 7 已匹配 8 已存单 9 已取消 10返销 11部分到账 + ArrivedAmount string `form:"arrived_amount" json:"arrived_amount" xml:"arrived_amount" uri:"arrived_amount" binding:"required"` // 到账金额 + OrderNo string `form:"order_no" json:"order_no" xml:"order_no" uri:"order_no" binding:"required"` // 第三方单号 + OrderNumber string `form:"order_number" json:"order_number" xml:"order_number" uri:"order_number" binding:"required"` // 微客云平台单号 + Amount string `form:"amount" json:"amount" xml:"amount" uri:"amount" binding:"required"` // 充值金额,如50,100,200可选 + Fanli float64 `form:"fanli" json:"fanli" xml:"fanli" uri:"fanli" binding:"required"` // 返利金额 + CostPrice float64 `form:"cost_price" json:"cost_price" xml:"cost_price" uri:"cost_price" binding:"required"` // 成本价格 + Sign string `form:"sign" json:"sign" xml:"sign" uri:"sign" binding:"omitempty"` // 加密内容 + FailReason string `form:"failReason" json:"failReason" xml:"failReason" uri:"failReason" binding:"omitempty"` // 失败原因,有些渠道没有返回,不是很准确,但电费失败大部分原因都是户号不对或者地区不对或者缴费金额小于欠费金额 +} + +// RestPowerPushOrderNotifyGin 电费充值API - 回调通知 +// https://open.wikeyun.cn/#/document/1/article/303 +func (c *Client) RestPowerPushOrderNotifyGin(ctx context.Context, ginCtx *gin.Context) (ResponseRestPowerPushOrderNotifyGin, error) { + + // 声明接收的变量 + var validateJson struct { + Status int `form:"status" json:"status" xml:"status" uri:"status" binding:"omitempty"` // 状态 订单状态 0 待支付 1 已付 充值中 2充值成功 3充值失败 需要退款 4退款成功 5已超时 6待充值 7 已匹配 8 已存单 9 已取消 10返销 11部分到账 + ArrivedAmount string `form:"arrived_amount" json:"arrived_amount" xml:"arrived_amount" uri:"arrived_amount" binding:"required"` // 到账金额 + OrderNo string `form:"order_no" json:"order_no" xml:"order_no" uri:"order_no" binding:"required"` // 第三方单号 + OrderNumber string `form:"order_number" json:"order_number" xml:"order_number" uri:"order_number" binding:"required"` // 微客云平台单号 + Amount string `form:"amount" json:"amount" xml:"amount" uri:"amount" binding:"required"` // 充值金额,如50,100,200可选 + Fanli float64 `form:"fanli" json:"fanli" xml:"fanli" uri:"fanli" binding:"required"` // 返利金额 + CostPrice float64 `form:"cost_price" json:"cost_price" xml:"cost_price" uri:"cost_price" binding:"required"` // 成本价格 + Sign string `form:"sign" json:"sign" xml:"sign" uri:"sign" binding:"omitempty"` // 加密内容 + FailReason string `form:"failReason" json:"failReason" xml:"failReason" uri:"failReason" binding:"omitempty"` // 失败原因,有些渠道没有返回,不是很准确,但电费失败大部分原因都是户号不对或者地区不对或者缴费金额小于欠费金额 + } + + err := ginCtx.ShouldBind(&validateJson) + + return validateJson, err +} diff --git a/service/wikeyun/rest.power.query.go b/service/wikeyun/rest.power.query.go index b2ad737b..9873215e 100644 --- a/service/wikeyun/rest.power.query.go +++ b/service/wikeyun/rest.power.query.go @@ -20,6 +20,7 @@ type RestPowerQueryResponse struct { CostPrice string `json:"cost_price"` OrderNumber string `json:"order_number"` ArrivedAmount int64 `json:"arrived_amount"` + Reason string `json:"reason"` } `json:"data"` } diff --git a/service/wikeyun/rest.recharge.push_order.go b/service/wikeyun/rest.recharge.push_order.go index 9a7d3f61..d5b09482 100644 --- a/service/wikeyun/rest.recharge.push_order.go +++ b/service/wikeyun/rest.recharge.push_order.go @@ -30,7 +30,7 @@ func newRestRechargePushOrderResult(result RestRechargePushOrderResponse, body [ func (c *Client) RestRechargePushOrder(ctx context.Context, notMustParams ...gorequest.Params) *RestRechargePushOrderResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("store_id", c.config.StoreId) // 店铺ID + params.Set("store_id", c.GetStoreId()) // 店铺ID // 请求 request, err := c.request(ctx, apiUrl+"/rest/Recharge/pushOrder", params) // 定义 diff --git a/service/wikeyun/rest.recharge.push_order.notify.gin.go b/service/wikeyun/rest.recharge.push_order.notify.gin.go new file mode 100644 index 00000000..2506821e --- /dev/null +++ b/service/wikeyun/rest.recharge.push_order.notify.gin.go @@ -0,0 +1,38 @@ +package wikeyun + +import ( + "context" + "github.com/gin-gonic/gin" +) + +type ResponseRestRechargePushOrderNotifyGin struct { + Status int `form:"status" json:"status" xml:"status" uri:"status" binding:"omitempty"` // 状态 订单状态 0 待支付 1 已付 充值中 2充值成功 3充值失败 需要退款 4退款成功 5已超时 6待充值 7 已匹配 8 已存单 9 已取消 10返销 11部分到账 + Mobile string `form:"mobile" json:"mobile" xml:"mobile" uri:"mobile" binding:"required"` // 充值手机号 + OrderNo string `form:"order_no" json:"order_no" xml:"order_no" uri:"order_no" binding:"required"` // 第三方单号 + OrderNumber string `form:"order_number" json:"order_number" xml:"order_number" uri:"order_number" binding:"required"` // 微客云平台单号 + Amount string `form:"amount" json:"amount" xml:"amount" uri:"amount" binding:"required"` // 充值金额,如50,100,200可选 + Fanli float64 `form:"fanli" json:"fanli" xml:"fanli" uri:"fanli" binding:"required"` // 返利金额 + CostPrice float64 `form:"cost_price" json:"cost_price" xml:"cost_price" uri:"cost_price" binding:"required"` // 成本价格 + Sign string `form:"sign" json:"sign" xml:"sign" uri:"sign" binding:"omitempty"` // 加密内容 +} + +// RestRechargePushOrderNotifyGin 话费充值推送 - 回调通知 +// https://open.wikeyun.cn/#/document/1/article/302 +func (c *Client) RestRechargePushOrderNotifyGin(ctx context.Context, ginCtx *gin.Context) (ResponseRestRechargePushOrderNotifyGin, error) { + + // 声明接收的变量 + var validateJson struct { + Status int `form:"status" json:"status" xml:"status" uri:"status" binding:"omitempty"` // 状态 订单状态 0 待支付 1 已付 充值中 2充值成功 3充值失败 需要退款 4退款成功 5已超时 6待充值 7 已匹配 8 已存单 9 已取消 10返销 11部分到账 + Mobile string `form:"mobile" json:"mobile" xml:"mobile" uri:"mobile" binding:"required"` // 充值手机号 + OrderNo string `form:"order_no" json:"order_no" xml:"order_no" uri:"order_no" binding:"required"` // 第三方单号 + OrderNumber string `form:"order_number" json:"order_number" xml:"order_number" uri:"order_number" binding:"required"` // 微客云平台单号 + Amount string `form:"amount" json:"amount" xml:"amount" uri:"amount" binding:"required"` // 充值金额,如50,100,200可选 + Fanli float64 `form:"fanli" json:"fanli" xml:"fanli" uri:"fanli" binding:"required"` // 返利金额 + CostPrice float64 `form:"cost_price" json:"cost_price" xml:"cost_price" uri:"cost_price" binding:"required"` // 成本价格 + Sign string `form:"sign" json:"sign" xml:"sign" uri:"sign" binding:"omitempty"` // 加密内容 + } + + err := ginCtx.ShouldBind(&validateJson) + + return validateJson, err +} diff --git a/service/wikeyun/sign.go b/service/wikeyun/sign.go index a5727ce7..a9eeb74b 100644 --- a/service/wikeyun/sign.go +++ b/service/wikeyun/sign.go @@ -25,26 +25,26 @@ func (c *Client) sign(params map[string]interface{}) respSign { v := "1.0" format := "json" timestamp := strconv.FormatInt(time.Now().Unix(), 10) - params["v"] = v // 客户端接口版本,目前是1.0 - params["format"] = format // 默认json - params["app_key"] = c.config.AppKey // 应用唯一表示 - params["client"] = c.clientIp // 客户端请求ip - params["timestamp"] = timestamp // unix时间戳(秒单位) + params["v"] = v // 客户端接口版本,目前是1.0 + params["format"] = format // 默认json + params["app_key"] = c.GetAppKey() // 应用唯一表示 + params["client"] = c.GetClientIp() // 客户端请求ip + params["timestamp"] = timestamp // unix时间戳(秒单位) // 排序所有的 key var keys []string for key := range params { keys = append(keys, key) } sort.Strings(keys) - signStr := c.config.AppSecret + signStr := c.GetAppSecret() for _, key := range keys { signStr += key + getString(params[key]) } - signStr += c.config.AppSecret + signStr += c.GetAppSecret() return respSign{ - AppKey: c.config.AppKey, + AppKey: c.GetAppKey(), Timestamp: timestamp, - Client: c.clientIp, + Client: c.GetClientIp(), V: v, Format: format, Sign: c.createSign(signStr),