pay.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package pay
  2. import (
  3. "crypto"
  4. "crypto/rand"
  5. "crypto/rsa"
  6. "crypto/x509"
  7. "encoding/base64"
  8. "encoding/pem"
  9. "errors"
  10. "fmt"
  11. "io/ioutil"
  12. "net/http"
  13. "net/url"
  14. "strings"
  15. "time"
  16. "zhiyuan/models"
  17. "zhiyuan/pkg/config"
  18. "zhiyuan/pkg/utils"
  19. "zhiyuan/services/weixin"
  20. )
  21. const (
  22. JsapiUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
  23. HeaderAuthorizationFormat = "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\""
  24. Authorization = "Authorization"
  25. Accept = "Accept"
  26. )
  27. type Client struct {
  28. Account *models.Weixin // 支付账号
  29. SignType string // 签名类型
  30. PrivateKey *rsa.PrivateKey
  31. }
  32. func NewClient(wxID int) (*Client, error) {
  33. weixinInfo, _ := weixin.GetOne(map[string]interface{}{"id": wxID}, nil, nil)
  34. private, err := LoadPrivateKey()
  35. if err != nil {
  36. return nil, err
  37. }
  38. return &Client{
  39. Account: weixinInfo,
  40. SignType: "RSA",
  41. PrivateKey: private,
  42. }, nil
  43. }
  44. func (c *Client) SignRequest(method string, requestUrl string, body string) (string, error) {
  45. u, err := url.Parse(requestUrl)
  46. timestamp := time.Now().Unix()
  47. nonce := utils.RandomStr()
  48. sign, err := c.Sign([]string{method, u.RequestURI(), utils.ToStr(timestamp), nonce, body})
  49. if err != nil {
  50. return "", err
  51. }
  52. return fmt.Sprintf(HeaderAuthorizationFormat,
  53. c.Account.MchID,
  54. nonce,
  55. timestamp,
  56. c.Account.SerialNO,
  57. sign,
  58. ), nil
  59. }
  60. func (c *Client) Sign(param []string) (string, error) {
  61. message := strings.Join(param, "\n") + "\n"
  62. return SignSHA256WithRSA(message, c.PrivateKey)
  63. }
  64. func (c *Client) Prepay(param JsapiParam) (*PrepayResponse, error) {
  65. if param.Description == "" || param.OutTradeNO == "" || param.Total <= 0 || param.OpenID == "" {
  66. return nil, errors.New("description,out_trade_no,open_id,money不能为空")
  67. }
  68. params := PrepayRequest{
  69. AppID: c.Account.AppID,
  70. MchID: c.Account.MchID,
  71. Description: param.Description,
  72. OutTradeNO: param.OutTradeNO,
  73. NotifyUrl: param.NotifyUrl,
  74. }
  75. params.Amount.Total = utils.FloatMul(param.Total, 100, 0)
  76. params.Payer.OpenID = param.OpenID
  77. fmt.Println(params)
  78. authorization, err := c.SignRequest("POST", JsapiUrl, utils.JsonEncode(params))
  79. if err != nil {
  80. return nil, err
  81. }
  82. header := SetHeaderAuthorization(authorization)
  83. var res *PrepayResponse
  84. if err := utils.HttpPostJSON(&http.Client{}, JsapiUrl, header, params, &res); err != nil {
  85. return nil, err
  86. }
  87. if res.PrepayID == "" {
  88. return nil, errors.New(res.Message)
  89. }
  90. return res, nil
  91. }
  92. func (c *Client) JsapiPay(param JsapiParam) (JsapiReturn, error) {
  93. res, err := c.Prepay(param)
  94. if err != nil {
  95. return JsapiReturn{}, err
  96. }
  97. retParam := JsapiReturn{
  98. AppID: c.Account.AppID,
  99. Timestamp: utils.ToStr(time.Now().Unix()),
  100. NonceStr: utils.RandomStr(),
  101. Package: "prepay_id=" + res.PrepayID,
  102. SignType: c.SignType,
  103. }
  104. if sign, err := c.Sign([]string{retParam.AppID, retParam.Timestamp, retParam.NonceStr, retParam.SignType}); err != nil {
  105. return JsapiReturn{}, err
  106. } else {
  107. retParam.PaySign = sign
  108. return retParam, nil
  109. }
  110. }
  111. func SetHeaderAuthorization(authorization string) http.Header {
  112. header := http.Header{}
  113. header.Set(Authorization, authorization)
  114. header.Set(Accept, "*/*")
  115. return header
  116. }
  117. func LoadPrivateKey() (*rsa.PrivateKey, error) {
  118. privateKeyStr, err := ioutil.ReadFile(utils.GetRootPath() + config.Cfg.App.WeixinPath + "apiclient_key.pem")
  119. block, _ := pem.Decode(privateKeyStr)
  120. if block == nil {
  121. return nil, fmt.Errorf("decode private key err")
  122. }
  123. key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
  124. if err != nil {
  125. return nil, fmt.Errorf("parse private key err:%s", err.Error())
  126. }
  127. privateKey, ok := key.(*rsa.PrivateKey)
  128. if !ok {
  129. return nil, fmt.Errorf("%s is not rsa private key", privateKeyStr)
  130. }
  131. return privateKey, nil
  132. }
  133. func SignSHA256WithRSA(source string, privateKey *rsa.PrivateKey) (signature string, err error) {
  134. if privateKey == nil {
  135. return "", fmt.Errorf("private key should not be nil")
  136. }
  137. h := crypto.Hash.New(crypto.SHA256)
  138. _, err = h.Write([]byte(source))
  139. if err != nil {
  140. return "", nil
  141. }
  142. hashed := h.Sum(nil)
  143. signatureByte, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
  144. if err != nil {
  145. return "", err
  146. }
  147. return base64.StdEncoding.EncodeToString(signatureByte), nil
  148. }