diff --git a/certificates.go b/certificates.go index fc203d3..62e6fca 100644 --- a/certificates.go +++ b/certificates.go @@ -34,9 +34,9 @@ func NewCertificatesResult(result CertificatesResponse, body []byte, http gorequ // Certificates 获取平台证书列表 // https://pay.weixin.qq.com/wiki/doc/apiv3/apis/wechatpay5_1.shtml -func (app *App) Certificates() *CertificatesResult { +func (c *Client) Certificates() *CertificatesResult { // 请求 - request, err := app.request("https://api.mch.weixin.qq.com/v3/certificates", map[string]interface{}{}, http.MethodGet) + request, err := c.request("https://api.mch.weixin.qq.com/v3/certificates", map[string]interface{}{}, http.MethodGet) if err != nil { return NewCertificatesResult(CertificatesResponse{}, request.ResponseBody, request, err) } diff --git a/const.go b/const.go index 9079682..f3c1f2e 100644 --- a/const.go +++ b/const.go @@ -10,7 +10,7 @@ const ( // SDK 相关信息 const ( - Version = "1.0.0" // SDK 版本 + Version = "1.0.1" // SDK 版本 UserAgentFormat = "WechatPay-Go/%s (%s) GO/%s" // UserAgent中的信息 ) diff --git a/pay.jsapi.go b/pay.jsapi.go index 98add24..706a2cb 100644 --- a/pay.jsapi.go +++ b/pay.jsapi.go @@ -22,26 +22,26 @@ type GetJsApiResult struct { } // GetJsApi JSAPI调起支付API https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_4.shtml -func (app *App) GetJsApi(param GetJsApi) (result GetJsApiResult, err error) { +func (c *Client) GetJsApi(param GetJsApi) (result GetJsApiResult, err error) { // sign params timeStamp := time.Now().Unix() nonce := gorandom.Alphanumeric(32) - result.AppId = app.subAppid + result.AppId = c.config.SubAppid result.TimeStamp = fmt.Sprintf("%v", timeStamp) // 时间戳 result.NonceStr = nonce // 随机字符串 result.Package = param.Package // 订单详情扩展字符串 // 签名 - message := fmt.Sprintf("%s\n%s\n%s\n%s\n", app.subAppid, fmt.Sprintf("%v", timeStamp), nonce, param.Package) + message := fmt.Sprintf("%s\n%s\n%s\n%s\n", c.config.SubAppid, fmt.Sprintf("%v", timeStamp), nonce, param.Package) - signBytes, err := app.signPKCS1v15(message, []byte(app.mchSslKey)) + signBytes, err := c.signPKCS1v15(message, []byte(c.config.MchSslKey)) if err != nil { return result, err } - sign := app.base64EncodeStr(signBytes) + sign := c.base64EncodeStr(signBytes) result.PaySign = sign // 签名 result.SignType = "RSA" // 签名方式 return result, nil diff --git a/pay.partner.transactions.id.go b/pay.partner.transactions.id.go index bde41bc..de37f4d 100644 --- a/pay.partner.transactions.id.go +++ b/pay.partner.transactions.id.go @@ -64,12 +64,12 @@ func NewPayPartnerTransactionsIdResult(result PayPartnerTransactionsIdResponse, // PayPartnerTransactionsId 微信支付订单号查询 // https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_2.shtml -func (app *App) PayPartnerTransactionsId(transactionId string) *PayPartnerTransactionsIdResult { +func (c *Client) PayPartnerTransactionsId(transactionId string) *PayPartnerTransactionsIdResult { // 参数 params := gorequest.NewParams() // 请求 // 请求 - request, err := app.request(fmt.Sprintf("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/id/%s?sp_mchid=%s&sub_mchid=%s", transactionId, app.spMchId, app.subMchId), params, http.MethodGet) + request, err := c.request(fmt.Sprintf("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/id/%s?sp_mchid=%s&sub_mchid=%s", transactionId, c.config.SpMchId, c.config.SubMchId), params, http.MethodGet) if err != nil { return NewPayPartnerTransactionsIdResult(PayPartnerTransactionsIdResponse{}, request.ResponseBody, request, err) } diff --git a/pay.partner.transactions.jsapi.go b/pay.partner.transactions.jsapi.go index 59bd31f..7b25a92 100644 --- a/pay.partner.transactions.jsapi.go +++ b/pay.partner.transactions.jsapi.go @@ -23,15 +23,15 @@ func NewPayPartnerTransactionsJsapiResult(result PayPartnerTransactionsJsapiResp // PayPartnerTransactionsJsapi JSAPI下单 // https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_1.shtml -func (app *App) PayPartnerTransactionsJsapi(notMustParams ...gorequest.Params) *PayPartnerTransactionsJsapiResult { +func (c *Client) PayPartnerTransactionsJsapi(notMustParams ...gorequest.Params) *PayPartnerTransactionsJsapiResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("sp_appid", app.spAppid) // 服务商应用ID - params.Set("sp_mchid", app.spMchId) // 服务商户号 - params.Set("sub_appid", app.subAppid) // 子商户应用ID - params.Set("sub_mchid", app.subMchId) // 子商户号 + 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) // 子商户号 // 请求 - request, err := app.request("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi", params, http.MethodPost) + request, err := c.request("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi", params, http.MethodPost) if err != nil { return NewPayPartnerTransactionsJsapiResult(PayPartnerTransactionsJsapiResponse{}, request.ResponseBody, request, err) } diff --git a/pay.partner.transactions.out-trade-no.close.go b/pay.partner.transactions.out-trade-no.close.go index 00a3352..989b107 100644 --- a/pay.partner.transactions.out-trade-no.close.go +++ b/pay.partner.transactions.out-trade-no.close.go @@ -18,13 +18,13 @@ func NewPayPartnerTransactionsOutTradeNoCloseResult(body []byte, http gorequest. // PayPartnerTransactionsOutTradeNoClose 关闭订单API // https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_3.shtml -func (app *App) PayPartnerTransactionsOutTradeNoClose(outTradeNo string) *PayPartnerTransactionsOutTradeNoCloseResult { +func (c *Client) PayPartnerTransactionsOutTradeNoClose(outTradeNo string) *PayPartnerTransactionsOutTradeNoCloseResult { // 参数 params := gorequest.NewParams() - params.Set("sp_mchid", app.spMchId) // 服务商户号 - params.Set("sub_mchid", app.subMchId) // 子商户号 + params.Set("sp_mchid", c.config.SpMchId) // 服务商户号 + params.Set("sub_mchid", c.config.SubMchId) // 子商户号 // 请求 - request, err := app.request(fmt.Sprintf("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/%s/close", outTradeNo), params, http.MethodPost) + request, err := c.request(fmt.Sprintf("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/%s/close", outTradeNo), params, http.MethodPost) if err != nil { return NewPayPartnerTransactionsOutTradeNoCloseResult(request.ResponseBody, request, err) } diff --git a/pay.partner.transactions.out-trade-no.go b/pay.partner.transactions.out-trade-no.go index f5b5798..de98b4b 100644 --- a/pay.partner.transactions.out-trade-no.go +++ b/pay.partner.transactions.out-trade-no.go @@ -67,11 +67,11 @@ func NewPayPartnerTransactionsOutTradeNoResult(result PayPartnerTransactionsOutT // PayPartnerTransactionsOutTradeNo 商户订单号查询 // https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_2.shtml -func (app *App) PayPartnerTransactionsOutTradeNo(outTradeNo string) *PayPartnerTransactionsOutTradeNoResult { +func (c *Client) PayPartnerTransactionsOutTradeNo(outTradeNo string) *PayPartnerTransactionsOutTradeNoResult { // 参数 params := gorequest.NewParams() // 请求 - request, err := app.request(fmt.Sprintf("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/%s?sp_mchid=%s&sub_mchid=%s", outTradeNo, app.spMchId, app.subMchId), params, http.MethodGet) + request, err := c.request(fmt.Sprintf("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/%s?sp_mchid=%s&sub_mchid=%s", outTradeNo, c.config.SpMchId, c.config.SubMchId), params, http.MethodGet) if err != nil { return NewPayPartnerTransactionsOutTradeNoResult(PayPartnerTransactionsOutTradeNoResponse{}, request.ResponseBody, request, err) } diff --git a/refund.domestic.refunds.go b/refund.domestic.refunds.go index 6095c97..51380f1 100644 --- a/refund.domestic.refunds.go +++ b/refund.domestic.refunds.go @@ -62,12 +62,12 @@ func NewRefundDomesticRefundsResult(result RefundDomesticRefundsResponse, body [ // RefundDomesticRefunds 申请退款API // https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_9.shtml -func (app *App) RefundDomesticRefunds(notMustParams ...gorequest.Params) *RefundDomesticRefundsResult { +func (c *Client) RefundDomesticRefunds(notMustParams ...gorequest.Params) *RefundDomesticRefundsResult { // 参数 params := gorequest.NewParamsWith(notMustParams...) - params.Set("sub_mchid", app.subMchId) // 子商户号 + params.Set("sub_mchid", c.config.SubMchId) // 子商户号 // 请求 - request, err := app.request("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds", params, http.MethodPost) + request, err := c.request("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds", params, http.MethodPost) if err != nil { return NewRefundDomesticRefundsResult(RefundDomesticRefundsResponse{}, request.ResponseBody, request, err) } diff --git a/refund.domestic.refunds.out_refund_no.go b/refund.domestic.refunds.out_refund_no.go index ed495f1..6ff1364 100644 --- a/refund.domestic.refunds.out_refund_no.go +++ b/refund.domestic.refunds.out_refund_no.go @@ -62,11 +62,11 @@ func NewRefundDomesticRefundsOutRefundNoResult(result RefundDomesticRefundsOutRe // RefundDomesticRefundsOutRefundNo 查询单笔退款API // https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_9.shtml -func (app *App) RefundDomesticRefundsOutRefundNo(outRefundNo string) *RefundDomesticRefundsOutRefundNoResult { +func (c *Client) RefundDomesticRefundsOutRefundNo(outRefundNo string) *RefundDomesticRefundsOutRefundNoResult { // 参数 params := gorequest.NewParams() // 请求 - request, err := app.request("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/"+outRefundNo+"?sub_mchid="+app.subMchId, params, http.MethodGet) + request, err := c.request("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/"+outRefundNo+"?sub_mchid="+c.config.SubMchId, params, http.MethodGet) if err != nil { return NewRefundDomesticRefundsOutRefundNoResult(RefundDomesticRefundsOutRefundNoResponse{}, request.ResponseBody, request, err) } diff --git a/sign.go b/sign.go index 4d32900..3ba563a 100644 --- a/sign.go +++ b/sign.go @@ -19,7 +19,7 @@ import ( ) // 对消息的散列值进行数字签名 -func (app *App) signPKCS1v15(msg string, privateKey []byte) ([]byte, error) { +func (c *Client) signPKCS1v15(msg string, privateKey []byte) ([]byte, error) { block, _ := pem.Decode(privateKey) if block == nil { @@ -36,7 +36,7 @@ func (app *App) signPKCS1v15(msg string, privateKey []byte) ([]byte, error) { return nil, errors.New("private key format error") } - sign, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, app.haSha256(msg)) + sign, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, c.haSha256(msg)) if err != nil { return nil, errors.New("sign error") } @@ -45,12 +45,12 @@ func (app *App) signPKCS1v15(msg string, privateKey []byte) ([]byte, error) { } // base编码 -func (app *App) base64EncodeStr(src []byte) string { +func (c *Client) base64EncodeStr(src []byte) string { return base64.StdEncoding.EncodeToString(src) } // sha256加密 -func (app *App) haSha256(str string) []byte { +func (c *Client) haSha256(str string) []byte { h := sha256.New() h.Write([]byte(str)) return h.Sum(nil) @@ -58,7 +58,7 @@ func (app *App) haSha256(str string) []byte { // 生成身份认证信息 // https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/qian-ming-sheng-cheng -func (app *App) authorization(method string, paramMap map[string]interface{}, rawUrl string) (token string, err error) { +func (c *Client) authorization(method string, paramMap map[string]interface{}, rawUrl string) (token string, err error) { // 请求报文主体 var signBody string @@ -86,7 +86,7 @@ func (app *App) authorization(method string, paramMap map[string]interface{}, ra // 构造签名串 message := fmt.Sprintf(SignatureMessageFormat, method, canonicalUrl, timestamp, nonce, signBody) - sign, err := app.signSHA256WithRSA(message, app.getRsa([]byte(app.mchSslKey))) + sign, err := c.signSHA256WithRSA(message, c.getRsa([]byte(c.config.MchSslKey))) if err != nil { return token, err @@ -94,14 +94,14 @@ func (app *App) authorization(method string, paramMap map[string]interface{}, ra authorization := fmt.Sprintf( HeaderAuthorizationFormat, getAuthorizationType(), - app.spMchId, nonce, timestamp, app.mchSslSerialNo, sign, + c.config.SpMchId, nonce, timestamp, c.config.MchSslSerialNo, sign, ) return authorization, nil } // 报文解密 -func (app *App) decryptGCM(aesKey, nonceV, ciphertextV, additionalDataV string) ([]byte, error) { +func (c *Client) decryptGCM(aesKey, nonceV, ciphertextV, additionalDataV string) ([]byte, error) { key := []byte(aesKey) nonce := []byte(nonceV) additionalData := []byte(additionalDataV) @@ -125,7 +125,7 @@ func (app *App) decryptGCM(aesKey, nonceV, ciphertextV, additionalDataV string) } // 对消息的散列值进行数字签名 -func (app *App) getRsa(privateKey []byte) *rsa.PrivateKey { +func (c *Client) getRsa(privateKey []byte) *rsa.PrivateKey { block, _ := pem.Decode(privateKey) if block == nil { @@ -146,7 +146,7 @@ func (app *App) getRsa(privateKey []byte) *rsa.PrivateKey { } // 通过私钥对字符串以 SHA256WithRSA 算法生成签名信息 -func (app *App) signSHA256WithRSA(source string, privateKey *rsa.PrivateKey) (signature string, err error) { +func (c *Client) signSHA256WithRSA(source string, privateKey *rsa.PrivateKey) (signature string, err error) { if privateKey == nil { return "", fmt.Errorf("private key should not be nil") } diff --git a/wechatpayopen.go b/wechatpayopen.go index 8286c8e..fa6849d 100644 --- a/wechatpayopen.go +++ b/wechatpayopen.go @@ -6,58 +6,64 @@ import ( "gorm.io/gorm" ) -// App 微信支付服务器 -type App 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 内容 - pgsql *gorm.DB // pgsql数据库 - client *gorequest.App // 请求客户端 - log *golog.Api // 日志服务 - logTableName string // 日志表名 - logStatus bool // 日志状态 +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 内容 + PgsqlDb *gorm.DB // pgsql数据库 } -// NewApp 实例化 -func NewApp(spAppid, spMchId, subAppid, subMchId, apiV2, apiV3, serialNo, mchSslSerialNo, mchSslCer, mchSslKey string, pgsql *gorm.DB) *App { - app := &App{spAppid: spAppid, spMchId: spMchId, subAppid: subAppid, subMchId: subMchId, apiV2: apiV2, apiV3: apiV3, serialNo: serialNo, mchSslSerialNo: mchSslSerialNo, mchSslCer: mchSslCer, mchSslKey: mchSslKey} - app.client = gorequest.NewHttp() - if pgsql != nil { - app.pgsql = pgsql - app.logStatus = true - app.logTableName = "wechatpayopen" - app.log = golog.NewApi(&golog.ApiConfig{ - Db: pgsql, - TableName: app.logTableName, +// Client 微信支付服务 +type Client struct { + client *gorequest.App // 请求客户端 + log *golog.Api // 日志服务 + logTableName string // 日志表名 + logStatus bool // 日志状态 + config *ConfigClient // 配置 +} + +// NewClient 实例化 +func NewClient(config *ConfigClient) *Client { + + c := &Client{config: config} + + c.client = gorequest.NewHttp() + if c.config.PgsqlDb != nil { + c.logStatus = true + c.logTableName = "wechatpayopen" + c.log = golog.NewApi(&golog.ApiConfig{ + Db: c.config.PgsqlDb, + TableName: c.logTableName, }) } - return app + + return c } -// NewAppConfig 实例化 -func (app *App) NewAppConfig(subAppid, subMchId string) *App { - app.subAppid = subAppid - app.subMchId = subMchId - return app +// SubConfig 子商户配置 +func (c *Client) SubConfig(subAppid, subMchId string) *Client { + c.config.SpAppid = subAppid + c.config.SubMchId = subMchId + return c } -func (app *App) request(url string, params map[string]interface{}, method string) (resp gorequest.Response, err error) { +func (c *Client) request(url string, params map[string]interface{}, method string) (resp gorequest.Response, err error) { // 认证 - authorization, err := app.authorization(method, params, url) + authorization, err := c.authorization(method, params, url) if err != nil { return gorequest.Response{}, err } // 创建请求 - client := app.client + client := c.client // 设置请求地址 client.SetUri(url) @@ -83,8 +89,8 @@ func (app *App) request(url string, params map[string]interface{}, method string } // 日志 - if app.logStatus == true { - go app.postgresqlLog(request) + if c.logStatus == true { + go c.postgresqlLog(request) } return request, err