wechat.go 3.7 KB

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