| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- package svc
- import (
- "crypto/aes"
- "crypto/cipher"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "net/http"
- "path"
- "time"
- "git.i2edu.net/i2/go-zero/core/stores/sqlx"
- "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) {
- uuid := utils.GetUUID()
- ube, err := json.Marshal(params)
- if err != nil {
- return "", err
- }
- err = wc.RdCli.SetWithExpire(fmt.Sprintf(prefix, uuid), string(ube), time.Duration(1)*time.Hour)
- return uuid, err
- }
- // GetQrParams defined TODO
- func (wc *Wechat) GetQrParams(prefix string, uuid string, params interface{}) error {
- ube := ""
- err := wc.RdCli.GetCache(fmt.Sprintf(prefix, uuid), &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})
- 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
- Wechat *Wechat
- Transformer transformclient.Transform
- }
- // GetUserId defined TODO
- func (sc *ServiceContext) GetUserId(r *http.Request) (int64, error) {
- parser := token.NewTokenParser(token.WithResetDuration(time.Minute))
- tok, err := parser.ParseToken(r, sc.Config.JwtAuth.AccessSecret, "")
- if err != nil {
- return 0, err
- }
- return tok.Claims.(jwt.MapClaims)["userId"].(int64), err
- }
- // GetSessionKey defined TODO
- func (sc *ServiceContext) GetSessionKey(r *http.Request) (string, error) {
- parser := token.NewTokenParser(token.WithResetDuration(time.Minute))
- tok, err := parser.ParseToken(r, sc.Config.JwtAuth.AccessSecret, "")
- if err != nil {
- return "", err
- }
- return tok.Claims.(jwt.MapClaims)["sessionKey"].(string), err
- }
- func NewServiceContext(c config.Config) *ServiceContext {
- svc := &ServiceContext{
- Config: c,
- SqlConn: sqlx.NewMysql(c.DataSource),
- Transformer: transformclient.NewTransform(zrpc.MustNewClient(c.Transform)),
- }
- svc.UserModel = model.NewUserModel(svc.SqlConn, c.Cache)
- svc.RdCli = svc.UserModel.CacheStorage()
- svc.Wechat = &Wechat{
- RdCli: svc.RdCli,
- c: c,
- }
- return svc
- }
|