wechat.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package svc
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "encoding/base64"
  6. "encoding/json"
  7. "fmt"
  8. "time"
  9. "git.i2edu.net/i2/i2-bill-api/internal/config"
  10. "git.i2edu.net/i2/i2-bill-api/internal/utils"
  11. "git.i2edu.net/i2/i2-bill-api/model"
  12. )
  13. // Wechat defined
  14. type Wechat struct {
  15. RdCli Cache
  16. c config.Config
  17. }
  18. // WechatPhonedecrypt defined TODO
  19. type WechatPhonedecrypt struct {
  20. PhoneNumber string `json:"phoneNumber"`
  21. PurePhoneNumber string `json:"purePhoneNumber"`
  22. CountryCode string `json:"countryCode"`
  23. Watermark struct {
  24. Appid string `json:"appid"`
  25. Timestamp int32 `json:"timestamp"`
  26. } `json:"watermark"`
  27. }
  28. // GetAccessToken defined TODO
  29. func (wc *Wechat) GetAccessToken() (string, error) {
  30. token := ""
  31. err := wc.RdCli.GetCache(cacheWechatTokenPrefix, &token)
  32. if err == model.ErrRdsNotFound || token == "" {
  33. req := utils.Get("https://api.weixin.qq.com/cgi-bin/token")
  34. req.Param("grant_type", "client_credential")
  35. req.Param("secret", wc.c.Weixin.Secret)
  36. req.Param("appid", wc.c.Weixin.Appid)
  37. var res = struct {
  38. AccessToken string `json:"access_token"`
  39. ExpiresIn int `json:"expires_in"`
  40. }{}
  41. err = req.ToJSON(&res)
  42. if err != nil {
  43. return "", err
  44. }
  45. token = res.AccessToken
  46. err := wc.RdCli.SetWithExpire(cacheWechatTokenPrefix, res.AccessToken, time.Duration((res.ExpiresIn-60*2))*time.Second)
  47. if err != nil {
  48. return "", err
  49. }
  50. }
  51. return token, nil
  52. }
  53. // GenQrId defined TODO
  54. func (wc *Wechat) GenQrId(prefix string, params interface{}) (string, error) {
  55. ube, err := json.Marshal(params)
  56. hashCode := utils.HashCode(string(ube))
  57. if err != nil {
  58. return "", err
  59. }
  60. err = wc.RdCli.SetWithExpire(fmt.Sprintf(prefix, hashCode), string(ube), time.Duration(1)*time.Hour)
  61. return fmt.Sprintf("%v", hashCode), err
  62. }
  63. // GenUserQrId defined TODO
  64. func (wc *Wechat) GenUserQrId(prefix string, userId int64, params interface{}) (string, error) {
  65. ube, err := json.Marshal(params)
  66. hashCode := utils.HashCode(string(ube))
  67. if err != nil {
  68. return "", err
  69. }
  70. qrId := fmt.Sprintf("u%v-%v", userId, hashCode)
  71. err = wc.RdCli.SetWithExpire(fmt.Sprintf(prefix, qrId), string(ube), time.Duration(1)*time.Hour)
  72. return qrId, err
  73. }
  74. // GetQrParams defined TODO
  75. func (wc *Wechat) GetQrParams(prefix string, id string, params interface{}) error {
  76. ube := ""
  77. err := wc.RdCli.GetCache(fmt.Sprintf(prefix, id), &ube)
  78. if err != nil {
  79. return err
  80. }
  81. err = json.Unmarshal([]byte(ube), params)
  82. if err != nil {
  83. return err
  84. }
  85. return err
  86. }
  87. // GetQrParams defined TODO
  88. func (wc *Wechat) DecryptMobile(sessionKey, encryptedData, iv string) (string, error) {
  89. key, err := base64.StdEncoding.DecodeString(sessionKey)
  90. if err != nil {
  91. return "", err
  92. }
  93. bIv, err := base64.StdEncoding.DecodeString(iv)
  94. if err != nil {
  95. return "", err
  96. }
  97. bEncryptedData, err := base64.StdEncoding.DecodeString(encryptedData)
  98. if err != nil {
  99. return "", err
  100. }
  101. block, err := aes.NewCipher(key)
  102. if err != nil {
  103. return "", err
  104. }
  105. var decrypt = bEncryptedData
  106. blockMode := cipher.NewCBCDecrypter(block, bIv)
  107. blockMode.CryptBlocks(decrypt, bEncryptedData)
  108. length := len(decrypt)
  109. unpadding := int(decrypt[length-1])
  110. decData := decrypt[:(length - unpadding)]
  111. decryptData := WechatPhonedecrypt{}
  112. err = json.Unmarshal(decData, &decryptData)
  113. if err != nil {
  114. return "", err
  115. }
  116. return decryptData.PhoneNumber, err
  117. }
  118. // GenQrCode defined TODO
  119. func (wc *Wechat) GenQrCode(scene, page string) (*model.I2billSysAttachment, error) {
  120. token, err := wc.GetAccessToken()
  121. if err != nil {
  122. return nil, err
  123. }
  124. req := utils.Post("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + token)
  125. req.JSONBody(map[string]interface{}{"scene": scene, "page": page, "is_hyaline": true})
  126. resp, err := req.Response()
  127. if err != nil {
  128. return nil, err
  129. }
  130. defer resp.Body.Close()
  131. oss, err := GetAliYunOssInstance()
  132. if err != nil {
  133. return nil, err
  134. }
  135. return oss.UploadRead(resp.Body, ".png")
  136. }