wx_pay.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package services
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "github.com/wechatpay-apiv3/wechatpay-go/core"
  8. "github.com/wechatpay-apiv3/wechatpay-go/core/option"
  9. "github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
  10. "github.com/wechatpay-apiv3/wechatpay-go/services/payments/native"
  11. payUtils "github.com/wechatpay-apiv3/wechatpay-go/utils"
  12. "hongze/hongze_web_mfyx/models"
  13. "hongze/hongze_web_mfyx/models/order"
  14. "hongze/hongze_web_mfyx/utils"
  15. "log"
  16. "time"
  17. )
  18. const (
  19. MchPKFileName = "../hongze_mfyx/utils/cert/apiclient_key.pem"
  20. Mchid = "1624495680"
  21. MchCertificateSerialNumber = "5ED2719CFAE5205763034AD80BF4B8A33533C418"
  22. MchAPIv3Key = "W1tbnzQrzQ7yRRNuQCIHjis8dgdasKVX"
  23. )
  24. // 微信商户建立连接
  25. func getWechatClient() (context.Context, *core.Client, error) {
  26. // 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
  27. mchPrivateKey, err := payUtils.LoadPrivateKeyWithPath(MchPKFileName)
  28. if err != nil {
  29. log.Print("load merchant private key error")
  30. return nil, nil, err
  31. }
  32. ctx := context.Background()
  33. // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
  34. opts := []core.ClientOption{
  35. option.WithWechatPayAutoAuthCipher(Mchid, MchCertificateSerialNumber, mchPrivateKey, MchAPIv3Key),
  36. }
  37. client, err := core.NewClient(ctx, opts...)
  38. if err != nil {
  39. log.Printf("new wechat pay client err:%s", err)
  40. return nil, nil, err
  41. }
  42. return ctx, client, nil
  43. }
  44. // 生成预支付交易单
  45. func ExampleJsapiApiServicePrepay(orderDetail *order.CygxOrder, unionId string) (JsapiApiResp order.PrepayWithRequestPaymentResponse, err error) {
  46. //var err error
  47. defer func() {
  48. if err != nil {
  49. fmt.Println(err)
  50. go utils.SendAlarmMsg(fmt.Sprint("生成预支付交易单失败 ExampleJsapiApiServicePrepay, err:", err.Error(), "unionId:", unionId), 2)
  51. }
  52. }()
  53. userRecord, e := models.GetUserRecordByUnionId(unionId)
  54. if e != nil && e.Error() != utils.ErrNoRow() {
  55. err = errors.New("GetUserRecordByUnionId, Err: " + e.Error())
  56. return
  57. }
  58. ctx, client, err := getWechatClient()
  59. if err != nil {
  60. log.Printf("getWechatClientt err:%s", err)
  61. return
  62. }
  63. svc := jsapi.JsapiApiService{Client: client}
  64. // 得到prepay_id,以及调起支付所需的参数和签名
  65. resp, _, err := svc.PrepayWithRequestPayment(ctx,
  66. jsapi.PrepayRequest{
  67. Appid: core.String(utils.WxAppId),
  68. Mchid: core.String(Mchid),
  69. Description: core.String(orderDetail.SourceTitle),
  70. OutTradeNo: core.String(orderDetail.OrderCode),
  71. Attach: core.String(""),
  72. NotifyUrl: core.String(utils.WxPayJsapiNotifyUrl),
  73. Amount: &jsapi.Amount{
  74. Total: core.Int64(int64(orderDetail.OrderMoney * 100)), // 分
  75. },
  76. Payer: &jsapi.Payer{
  77. Openid: core.String(userRecord.OpenId),
  78. },
  79. },
  80. )
  81. JsapiApiResp.PrepayId = *resp.PrepayId
  82. JsapiApiResp.Appid = *resp.Appid
  83. JsapiApiResp.TimeStamp = *resp.TimeStamp
  84. JsapiApiResp.NonceStr = *resp.NonceStr
  85. JsapiApiResp.Package = *resp.Package
  86. JsapiApiResp.SignType = *resp.SignType
  87. JsapiApiResp.PaySign = *resp.PaySign
  88. return
  89. }
  90. //func init() {
  91. // ExampleNativeApiService_Prepay()
  92. //}
  93. func ExampleNativeApiServicePrepay(orderDetail *order.CygxOrder) (codeUrl string, err error) {
  94. defer func() {
  95. if err != nil {
  96. fmt.Println(err)
  97. go utils.SendAlarmMsg(fmt.Sprint("生成预支付交易单失败 ExampleNativeApiServicePrepay, err:", err.Error(), "OrderCode:", orderDetail.OrderCode), 2)
  98. }
  99. }()
  100. //如果是试用卡,商品名称就显示日卡月卡,如果是单场付费就显示,单场活动名称
  101. if orderDetail.OrderType == 1 {
  102. orderDetail.SourceTitle = "畅读" + orderDetail.GoodsName
  103. }
  104. ctx, client, _ := getWechatClient()
  105. svc := native.NativeApiService{Client: client}
  106. resp, _, err := svc.Prepay(ctx,
  107. native.PrepayRequest{
  108. Appid: core.String(utils.WxAppId),
  109. Mchid: core.String(Mchid),
  110. Description: core.String(orderDetail.SourceTitle),
  111. OutTradeNo: core.String(orderDetail.OutTradeNo),
  112. TimeExpire: core.Time(time.Now().Add(10 * time.Minute)),
  113. Attach: core.String(""),
  114. NotifyUrl: core.String(utils.WxPayJsapiNotifyUrl),
  115. GoodsTag: core.String(""),
  116. SupportFapiao: core.Bool(false),
  117. Amount: &native.Amount{
  118. Currency: core.String("CNY"),
  119. Total: core.Int64(int64(orderDetail.OrderMoney * 100)), // 分
  120. },
  121. },
  122. )
  123. if err != nil {
  124. return
  125. }
  126. codeUrl = *resp.CodeUrl
  127. return
  128. }
  129. type WechatPayCallback struct {
  130. MchID string `json:"mchid"`
  131. AppID string `json:"appid"`
  132. OutTradeNo string `json:"out_trade_no"`
  133. TransactionID string `json:"transaction_id"`
  134. TradeType string `json:"trade_type"`
  135. TradeState string `json:"trade_state"`
  136. TradeStateDesc string `json:"trade_state_desc"`
  137. BankType string `json:"bank_type"`
  138. Attach string `json:"attach"`
  139. SuccessTime time.Time `json:"success_time"`
  140. Payer struct {
  141. OpenID string `json:"openid"`
  142. } `json:"payer"`
  143. Amount struct {
  144. Total int `json:"total"`
  145. PayerTotal int `json:"payer_total"`
  146. Currency string `json:"currency"`
  147. PayerCurrency string `json:"payer_currency"`
  148. } `json:"amount"`
  149. }
  150. // 微信支付回调内容解密
  151. func WxDecodeNotify(body []byte) (wechatPayCallback *WechatPayCallback) {
  152. var err error
  153. defer func() {
  154. if err != nil {
  155. fmt.Println(err)
  156. go utils.SendAlarmMsg(fmt.Sprint("微信支付回调内容解密失败 WxDecodeNotify, err:", err.Error()), 2)
  157. }
  158. }()
  159. var prepaymap map[string]interface{}
  160. _ = json.Unmarshal(body, &prepaymap)
  161. var prepaymap2 = prepaymap["resource"].(map[string]interface{})
  162. nonce := prepaymap2["nonce"].(string)
  163. associatedData := prepaymap2["associated_data"].(string)
  164. ciphertext := prepaymap2["ciphertext"].(string)
  165. tx, e := payUtils.DecryptAES256GCM(MchAPIv3Key, associatedData, nonce, ciphertext)
  166. if e != nil {
  167. log.Println(err)
  168. return
  169. }
  170. if e != nil {
  171. err = errors.New("DecryptAES256GCM, Err: " + e.Error())
  172. return
  173. }
  174. var datamap *WechatPayCallback
  175. _ = json.Unmarshal([]byte(tx), &datamap)
  176. wechatPayCallback = datamap
  177. return
  178. }