|
|
@@ -2,13 +2,9 @@ package svc
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
- "crypto/aes"
|
|
|
- "crypto/cipher"
|
|
|
- "encoding/base64"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
"net/http"
|
|
|
- "path"
|
|
|
"strconv"
|
|
|
"time"
|
|
|
|
|
|
@@ -16,157 +12,18 @@ import (
|
|
|
"git.i2edu.net/i2/go-zero/rest/token"
|
|
|
"git.i2edu.net/i2/go-zero/zrpc"
|
|
|
"git.i2edu.net/i2/i2-bill-api/internal/config"
|
|
|
- "git.i2edu.net/i2/i2-bill-api/internal/utils"
|
|
|
"git.i2edu.net/i2/i2-bill-api/model"
|
|
|
"git.i2edu.net/i2/i2-bill-erp/transformclient"
|
|
|
"github.com/dgrijalva/jwt-go"
|
|
|
)
|
|
|
|
|
|
-const cacheWechatTokenPrefix = "cache:wechat:token:"
|
|
|
-
|
|
|
-// RdCli defined
|
|
|
-type RdCli interface {
|
|
|
- SetCache(key string, v interface{}) error
|
|
|
- GetCache(key string, v interface{}) error
|
|
|
- SetWithExpire(key string, v interface{}, expire time.Duration) error
|
|
|
-}
|
|
|
-
|
|
|
-// Wechat defined
|
|
|
-type Wechat struct {
|
|
|
- RdCli RdCli
|
|
|
- c config.Config
|
|
|
-}
|
|
|
-
|
|
|
-// WechatPhonedecrypt defined TODO
|
|
|
-type WechatPhonedecrypt struct {
|
|
|
- PhoneNumber string `json:"phoneNumber"`
|
|
|
- PurePhoneNumber string `json:"purePhoneNumber"`
|
|
|
- CountryCode string `json:"countryCode"`
|
|
|
- Watermark struct {
|
|
|
- Appid string `json:"appid"`
|
|
|
- Timestamp int32 `json:"timestamp"`
|
|
|
- } `json:"watermark"`
|
|
|
-}
|
|
|
-
|
|
|
-// GetAccessToken defined TODO
|
|
|
-func (wc *Wechat) GetAccessToken() (string, error) {
|
|
|
- token := ""
|
|
|
- err := wc.RdCli.GetCache(cacheWechatTokenPrefix, &token)
|
|
|
- if err == model.ErrRdsNotFound {
|
|
|
- req := utils.Get("https://api.weixin.qq.com/cgi-bin/token")
|
|
|
- req.Param("grant_type", "client_credential")
|
|
|
- req.Param("secret", wc.c.Weixin.Secret)
|
|
|
- req.Param("appid", wc.c.Weixin.Appid)
|
|
|
- var res = struct {
|
|
|
- AccessToken string `json:"access_token"`
|
|
|
- ExpiresIn int `json:"expires_in"`
|
|
|
- }{}
|
|
|
- err = req.ToJSON(&res)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- token = res.AccessToken
|
|
|
- err := wc.RdCli.SetWithExpire(cacheWechatTokenPrefix, res.AccessToken, time.Duration((res.ExpiresIn-60*2))*time.Second)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- }
|
|
|
- return token, nil
|
|
|
-}
|
|
|
-
|
|
|
-// GenQrId defined TODO
|
|
|
-func (wc *Wechat) GenQrId(prefix string, params interface{}) (string, error) {
|
|
|
- timestamp := utils.GetTimestamp()
|
|
|
- ube, err := json.Marshal(params)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- err = wc.RdCli.SetWithExpire(fmt.Sprintf(prefix, timestamp), string(ube), time.Duration(1)*time.Hour)
|
|
|
- return fmt.Sprintf("%v", timestamp), err
|
|
|
-}
|
|
|
-
|
|
|
-// GenUserQrId defined TODO
|
|
|
-func (wc *Wechat) GenUserQrId(prefix string, userId int64, params interface{}) (string, error) {
|
|
|
- timestamp := utils.GetTimestamp()
|
|
|
- ube, err := json.Marshal(params)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- qrId := fmt.Sprintf("u%v-%v", userId, timestamp)
|
|
|
- err = wc.RdCli.SetWithExpire(fmt.Sprintf(prefix, qrId), string(ube), time.Duration(1)*time.Hour)
|
|
|
- return qrId, err
|
|
|
-}
|
|
|
-
|
|
|
-// GetQrParams defined TODO
|
|
|
-func (wc *Wechat) GetQrParams(prefix string, id string, params interface{}) error {
|
|
|
- ube := ""
|
|
|
- err := wc.RdCli.GetCache(fmt.Sprintf(prefix, id), &ube)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- err = json.Unmarshal([]byte(ube), params)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- return err
|
|
|
-}
|
|
|
-
|
|
|
-// GetQrParams defined TODO
|
|
|
-func (wc *Wechat) DecryptMobile(sessionKey, encryptedData, iv string) (string, error) {
|
|
|
- key, err := base64.StdEncoding.DecodeString(sessionKey)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- bIv, err := base64.StdEncoding.DecodeString(iv)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- bEncryptedData, err := base64.StdEncoding.DecodeString(encryptedData)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- block, err := aes.NewCipher(key)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- var decrypt = bEncryptedData
|
|
|
- blockMode := cipher.NewCBCDecrypter(block, bIv)
|
|
|
- blockMode.CryptBlocks(decrypt, bEncryptedData)
|
|
|
- length := len(decrypt)
|
|
|
- unpadding := int(decrypt[length-1])
|
|
|
- decData := decrypt[:(length - unpadding)]
|
|
|
-
|
|
|
- decryptData := WechatPhonedecrypt{}
|
|
|
- err = json.Unmarshal(decData, &decryptData)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- return decryptData.PhoneNumber, err
|
|
|
-}
|
|
|
-
|
|
|
-// GenQrCode defined TODO
|
|
|
-func (wc *Wechat) GenQrCode(scene, page string) (string, error) {
|
|
|
- token, err := wc.GetAccessToken()
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- req := utils.Post("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + token)
|
|
|
- req.JSONBody(map[string]interface{}{"scene": scene, "page": page})
|
|
|
- ph := path.Join("asserts", "qrcode", scene+".png")
|
|
|
- err = req.ToFile(ph)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- return ph, err
|
|
|
-}
|
|
|
-
|
|
|
type ServiceContext struct {
|
|
|
Config config.Config
|
|
|
SqlConn sqlx.SqlConn
|
|
|
- UserModel model.UserModel
|
|
|
- RdCli RdCli
|
|
|
+ RdCli Cache
|
|
|
Wechat *Wechat
|
|
|
Transformer transformclient.Transform
|
|
|
+ UserModel model.UserModel
|
|
|
}
|
|
|
|
|
|
// GetUserId defined TODO
|