1
This commit is contained in:
@@ -21,11 +21,7 @@ const (
|
|||||||
|
|
||||||
// WeChatPhoneNumberParam 微信登陆
|
// WeChatPhoneNumberParam 微信登陆
|
||||||
type WeChatPhoneNumberParam struct {
|
type WeChatPhoneNumberParam struct {
|
||||||
EncryptedData string `json:"encrypted_data" form:"encrypted_data" binding:"required"` // 加密信息
|
Code string `json:"code" form:"code" binding:"required"` //code
|
||||||
IV string `json:"iv" form:"iv" binding:"required"` // 加密算法初始量
|
|
||||||
NickName string `json:"nick_name" form:"nick_name" binding:"required"` // 昵称
|
|
||||||
HeadUrl string `json:"head_url" form:"head_url" binding:"required"` //头像图片地址
|
|
||||||
Code string `json:"code" form:"code" binding:"required"` //code
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type WxLoginReq struct {
|
type WxLoginReq struct {
|
||||||
@@ -33,16 +29,3 @@ type WxLoginReq struct {
|
|||||||
Phone string `json:"phone" form:"phone"` // 微信和电话登录使用
|
Phone string `json:"phone" form:"phone"` // 微信和电话登录使用
|
||||||
Password string `json:"password" form:"password"` // 密码登录
|
Password string `json:"password" form:"password"` // 密码登录
|
||||||
}
|
}
|
||||||
|
|
||||||
// 微信小程序解密后 用户手机号结构体
|
|
||||||
type UserPhone struct {
|
|
||||||
PhoneNumber string `json:"phoneNumber,omitempty"`
|
|
||||||
PurePhoneNumber string `json:"purePhoneNumber,omitempty"`
|
|
||||||
CountryCode string `json:"countryCode,omitempty"`
|
|
||||||
Watermark *watermarkInfo `json:"watermark,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type watermarkInfo struct {
|
|
||||||
Appid string `json:"appid,omitempty"`
|
|
||||||
Timestamp int `json:"timestamp,omitempty"`
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package app_server
|
package app_server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -17,7 +14,6 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -106,72 +102,7 @@ func (u *UserLogin) WxLogin(ctx *gin.Context, code, phone string) (*model.User,
|
|||||||
|
|
||||||
// GetUserPhoneNum 解密用户手机号
|
// GetUserPhoneNum 解密用户手机号
|
||||||
func (u *UserLogin) GetUserPhoneNum(param *wxLogin.WeChatPhoneNumberParam) (string, error) {
|
func (u *UserLogin) GetUserPhoneNum(param *wxLogin.WeChatPhoneNumberParam) (string, error) {
|
||||||
sessionInfo, err := api.WeixinMiniAPI.SNSCode2Session(param.Code)
|
return api.WeixinMiniAPI.SNSGetUserPhone(param.Code)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
weChatLogin := new(wxLogin.UserPhone)
|
|
||||||
if err := DecryptOpenDataToStruct(param.EncryptedData, param.IV, sessionInfo.SessionKey, weChatLogin); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return weChatLogin.PhoneNumber, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptOpenDataToStruct 解密开放数据到结构体
|
|
||||||
// encryptedData:包括敏感数据在内的完整用户信息的加密数据,小程序获取到
|
|
||||||
// iv:加密算法的初始向量,小程序获取到
|
|
||||||
// sessionKey:会话密钥,通过 gopay.Code2Session() 方法获取到
|
|
||||||
// beanPtr:需要解析到的结构体指针,操作完后,声明的结构体会被赋值
|
|
||||||
// 文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
|
|
||||||
func DecryptOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr interface{}) (err error) {
|
|
||||||
if encryptedData == "" || iv == "" || sessionKey == "" {
|
|
||||||
return errors.New("input params can not null")
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
cipherText, aesKey, ivKey, plainText []byte
|
|
||||||
block cipher.Block
|
|
||||||
blockMode cipher.BlockMode
|
|
||||||
)
|
|
||||||
beanValue := reflect.ValueOf(beanPtr)
|
|
||||||
if beanValue.Kind() != reflect.Ptr {
|
|
||||||
return errors.New("传入beanPtr类型必须是以指针形式")
|
|
||||||
}
|
|
||||||
if beanValue.Elem().Kind() != reflect.Struct {
|
|
||||||
return errors.New("传入interface{}必须是结构体")
|
|
||||||
}
|
|
||||||
cipherText, _ = base64.StdEncoding.DecodeString(encryptedData)
|
|
||||||
aesKey, _ = base64.StdEncoding.DecodeString(sessionKey)
|
|
||||||
ivKey, _ = base64.StdEncoding.DecodeString(iv)
|
|
||||||
if len(cipherText)%len(aesKey) != 0 {
|
|
||||||
return errors.New("encryptedData is error")
|
|
||||||
}
|
|
||||||
if block, err = aes.NewCipher(aesKey); err != nil {
|
|
||||||
return fmt.Errorf("aes.NewCipher:%w", err)
|
|
||||||
}
|
|
||||||
blockMode = cipher.NewCBCDecrypter(block, ivKey)
|
|
||||||
plainText = make([]byte, len(cipherText))
|
|
||||||
blockMode.CryptBlocks(plainText, cipherText)
|
|
||||||
if len(plainText) > 0 {
|
|
||||||
plainText = PKCS7UnPadding(plainText)
|
|
||||||
}
|
|
||||||
if err = json.Unmarshal(plainText, beanPtr); err != nil {
|
|
||||||
return fmt.Errorf("json.Marshal(%s):%w", string(plainText), err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解密填充模式(去除补全码) PKCS7UnPadding
|
|
||||||
// 解密时,需要在最后面去掉加密时添加的填充byte
|
|
||||||
func PKCS7UnPadding(origData []byte) (bs []byte) {
|
|
||||||
length := len(origData)
|
|
||||||
unPaddingNumber := int(origData[length-1]) // 找到Byte数组最后的填充byte 数字
|
|
||||||
if unPaddingNumber <= 16 {
|
|
||||||
bs = origData[:(length - unPaddingNumber)] // 只截取返回有效数字内的byte数组
|
|
||||||
} else {
|
|
||||||
bs = origData
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jxc4UserToken 全局变量,缓存菜市管理系统token
|
// Jxc4UserToken 全局变量,缓存菜市管理系统token
|
||||||
|
|||||||
Reference in New Issue
Block a user