wechat_servier_api.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. //==================================
  2. // * Name:Jerry
  3. // * DateTime:2019/5/6 13:16
  4. // * Desc:
  5. //==================================
  6. package gopay
  7. import (
  8. "bytes"
  9. "crypto/aes"
  10. "crypto/cipher"
  11. "crypto/hmac"
  12. "crypto/md5"
  13. "crypto/sha256"
  14. "crypto/tls"
  15. "encoding/base64"
  16. "encoding/hex"
  17. "encoding/json"
  18. "errors"
  19. "github.com/parnurzeal/gorequest"
  20. "reflect"
  21. "strings"
  22. )
  23. func HttpAgent() (agent *gorequest.SuperAgent) {
  24. agent = gorequest.New()
  25. agent.TLSClientConfig(&tls.Config{InsecureSkipVerify: true})
  26. return
  27. }
  28. //JSAPI支付,支付参数后,再次计算出小程序用的paySign
  29. func GetMiniPaySign(appId, nonceStr, prepayId, signType, timeStamp, apiKey string) (paySign string) {
  30. buffer := new(bytes.Buffer)
  31. buffer.WriteString("appId=")
  32. buffer.WriteString(appId)
  33. buffer.WriteString("&nonceStr=")
  34. buffer.WriteString(nonceStr)
  35. buffer.WriteString("&package=")
  36. buffer.WriteString(prepayId)
  37. buffer.WriteString("&signType=")
  38. buffer.WriteString(signType)
  39. buffer.WriteString("&timeStamp=")
  40. buffer.WriteString(timeStamp)
  41. buffer.WriteString("&key=")
  42. buffer.WriteString(apiKey)
  43. signStr := buffer.String()
  44. var hashSign []byte
  45. if signType == SignType_MD5 {
  46. hash := md5.New()
  47. hash.Write([]byte(signStr))
  48. hashSign = hash.Sum(nil)
  49. } else {
  50. hash := hmac.New(sha256.New, []byte(apiKey))
  51. hash.Write([]byte(signStr))
  52. hashSign = hash.Sum(nil)
  53. }
  54. paySign = strings.ToUpper(hex.EncodeToString(hashSign))
  55. return
  56. }
  57. //JSAPI支付,支付参数后,再次计算出微信内H5支付需要用的paySign
  58. func GetH5PaySign(appId, nonceStr, prepayId, signType, timeStamp, apiKey string) (paySign string) {
  59. buffer := new(bytes.Buffer)
  60. buffer.WriteString("appId=")
  61. buffer.WriteString(appId)
  62. buffer.WriteString("&nonceStr=")
  63. buffer.WriteString(nonceStr)
  64. buffer.WriteString("&package=")
  65. buffer.WriteString(prepayId)
  66. buffer.WriteString("&signType=")
  67. buffer.WriteString(signType)
  68. buffer.WriteString("&timeStamp=")
  69. buffer.WriteString(timeStamp)
  70. buffer.WriteString("&key=")
  71. buffer.WriteString(apiKey)
  72. signStr := buffer.String()
  73. var hashSign []byte
  74. if signType == SignType_MD5 {
  75. hash := md5.New()
  76. hash.Write([]byte(signStr))
  77. hashSign = hash.Sum(nil)
  78. } else {
  79. hash := hmac.New(sha256.New, []byte(apiKey))
  80. hash.Write([]byte(signStr))
  81. hashSign = hash.Sum(nil)
  82. }
  83. paySign = strings.ToUpper(hex.EncodeToString(hashSign))
  84. return
  85. }
  86. //解密开放数据
  87. // encryptedData:包括敏感数据在内的完整用户信息的加密数据
  88. // iv:加密算法的初始向量
  89. // sessionKey:会话密钥
  90. // beanPtr:需要解析到的结构体指针
  91. func DecryptOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr interface{}) (err error) {
  92. //验证参数类型
  93. beanValue := reflect.ValueOf(beanPtr)
  94. if beanValue.Kind() != reflect.Ptr {
  95. return errors.New("传入beanPtr类型必须是以指针形式")
  96. }
  97. //验证interface{}类型
  98. if beanValue.Elem().Kind() != reflect.Struct {
  99. return errors.New("传入interface{}必须是结构体")
  100. }
  101. aesKey, _ := base64.StdEncoding.DecodeString(sessionKey)
  102. ivKey, _ := base64.StdEncoding.DecodeString(iv)
  103. cipherText, _ := base64.StdEncoding.DecodeString(encryptedData)
  104. if len(cipherText)%len(aesKey) != 0 {
  105. return errors.New("encryptedData is error")
  106. }
  107. //fmt.Println("cipherText:", cipherText)
  108. block, err := aes.NewCipher(aesKey)
  109. if err != nil {
  110. return err
  111. }
  112. //解密
  113. blockMode := cipher.NewCBCDecrypter(block, ivKey)
  114. plainText := make([]byte, len(cipherText))
  115. blockMode.CryptBlocks(plainText, cipherText)
  116. //fmt.Println("plainText1:", plainText)
  117. plainText = PKCS7UnPadding(plainText)
  118. //fmt.Println("plainText:", plainText)
  119. //解析
  120. err = json.Unmarshal(plainText, beanPtr)
  121. if err != nil {
  122. return err
  123. }
  124. return nil
  125. }
  126. //获取微信用户的OpenId、SessionKey、UnionId
  127. // appId:APPID
  128. // appSecret:AppSecret
  129. // wxCode:小程序调用wx.login 获取的code
  130. func Code2Session(appId, appSecret, wxCode string) (sessionRsp *Code2SessionRsp, err error) {
  131. sessionRsp = new(Code2SessionRsp)
  132. url := "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + wxCode + "&grant_type=authorization_code"
  133. agent := HttpAgent()
  134. _, _, errs := agent.Get(url).EndStruct(sessionRsp)
  135. if len(errs) > 0 {
  136. return nil, errs[0]
  137. } else {
  138. return sessionRsp, nil
  139. }
  140. }
  141. //获取小程序全局唯一后台接口调用凭据(AccessToken:157字符)
  142. // appId:APPID
  143. // appSecret:AppSecret
  144. func GetAccessToken(appId, appSecret string) (accessToken *AccessToken, err error) {
  145. accessToken = new(AccessToken)
  146. url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret
  147. agent := HttpAgent()
  148. _, _, errs := agent.Get(url).EndStruct(accessToken)
  149. if len(errs) > 0 {
  150. return nil, errs[0]
  151. } else {
  152. return accessToken, nil
  153. }
  154. }
  155. //用户支付完成后,获取该用户的 UnionId,无需用户授权。
  156. // accessToken:接口调用凭据
  157. // openId:用户的OpenID
  158. // transactionId:微信支付订单号
  159. func GetPaidUnionId(accessToken, openId, transactionId string) (unionId *PaidUnionId, err error) {
  160. unionId = new(PaidUnionId)
  161. url := "https://api.weixin.qq.com/wxa/getpaidunionid?access_token=" + accessToken + "&openid=" + openId + "&transaction_id=" + transactionId
  162. agent := HttpAgent()
  163. _, _, errs := agent.Get(url).EndStruct(unionId)
  164. if len(errs) > 0 {
  165. return nil, errs[0]
  166. } else {
  167. return unionId, nil
  168. }
  169. }
  170. //获取用户基本信息(UnionID机制)
  171. // accessToken:接口调用凭据
  172. // openId:用户的OpenID
  173. // lang:默认为 zh_CN ,可选填 zh_CN 简体,zh_TW 繁体,en 英语
  174. func GetWeChatUserInfo(accessToken, openId string, lang ...string) (userInfo *WeChatUserInfo, err error) {
  175. userInfo = new(WeChatUserInfo)
  176. var url string
  177. if len(lang) > 0 {
  178. url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=" + lang[0]
  179. } else {
  180. url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN"
  181. }
  182. agent := HttpAgent()
  183. _, _, errs := agent.Get(url).EndStruct(userInfo)
  184. if len(errs) > 0 {
  185. return nil, errs[0]
  186. } else {
  187. return userInfo, nil
  188. }
  189. }