700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > golang 获取支付宝小程序用户手机号 登录授权 AES解密

golang 获取支付宝小程序用户手机号 登录授权 AES解密

时间:2018-11-21 13:03:15

相关推荐

golang 获取支付宝小程序用户手机号 登录授权 AES解密

目前支付宝官方的api没有关于golang语言的sdk,最近在开发支付宝小程序登录,发现支付宝对于敏感信息会进行AES加密,例如获取用户手机号,会先由前端获取手机号密文、传给服务端,进行解密,从而获取手机号,目前百度和google到的示例都不好用,内容同质化明显。手机号只做了AES解密。关于手机号sign校验,还没看懂支付宝官方文档是什么意思,验签逻辑说的比较笼统,所以还没有写。下面是解密示例。

package aliimport ("account-api-v3/models/user""account-api-v3/pkg/config""account-api-v3/pkg/e""account-api-v3/pkg/http""account-api-v3/pkg/logger""account-api-v3/pkg/oauth2/errors""crypto""crypto/aes""crypto/cipher""crypto/rand""crypto/rsa""crypto/sha256""crypto/x509""encoding/base64""encoding/json""encoding/pem""fmt""io/ioutil""reflect""sort""strings""time")const (// PEMBEGIN 私钥 PEMBEGIN 开头PEMBEGIN = "-----BEGIN RSA PRIVATE KEY-----\n"// PEMEND 私钥 PEMEND 结尾PEMEND = "\n-----END RSA PRIVATE KEY-----"// PUBPEMBEGIN 公钥 PEMBEGIN 开头PUBPEMBEGIN = "-----BEGIN PUBLIC KEY-----\n"// PUBPEMEND 公钥 PEMEND 结尾PUBPEMEND = "\n-----END PUBLIC KEY-----")type (CodeSession struct {ErrorResponse ErrorResponse `json:"error_response"`AlipaySystemOauthTokenResponse AlipaySystemOauthTokenResponse `json:"alipay_system_oauth_token_response"`Sign string`json:"sign"`}AlipaySystemOauthTokenResponse struct {AlipayUserId string `json:"alipay_user_id"`UserId string `json:"user_id"`AccessToken string `json:"access_token"`ExpiresIn string `json:"expires_in"`RefreshToken string `json:"refresh_token"`ReExpiresIn string `json:"re_expires_in"`AuthStart string `json:"auth_start"`}ErrorResponse struct {Code string `json:"code"`Msgstring `json:"msg"`SubCode string `json:"sub_code"`SubMsg string `json:"sub_msg"`}UserRes struct {ErrorResponseErrorResponse`json:"error_response"`AlipayUserInfoShareResponse AlipayUserInfoShareResponse `json:"alipay_user_info_share_response"`Sign string `json:"sign"`}AlipayUserInfoShareResponse struct {Codestring `json:"code"`Msgstring `json:"msg"`UserId string `json:"user_id"`Avatar string `json:"avatar"`Citystring `json:"city"`NickName string `json:"nick_name"`Province string `json:"province"`Gender string `json:"gender"`}MobileRes struct {Code string `json:"code"`Msg string `json:"msg"`Mobile string `json:"mobile"`}UserPhone struct {ErrorResponseMobile string `json:"mobile,omitempty"`})// 解密用户手机号密文// @content 手机号密文、sign密文签名func GetUserMobile(content, sign string) string {phone := new(UserPhone)// todo 验签,支付宝官方目前没有go相关的sdk,验签功能还没有实现,只做了密文解密,后续如果成功验签,会跟新// 解密密文err := DecryptOpenDataToStruct(content, config.AliMiniLogin.AesSecret, phone)if err == nil {return phone.Mobile}return ""}func DecryptOpenDataToStruct(encryptedData, secretKey string, beanPtr interface{}) (err error) {if encryptedData == "" || secretKey == "" {return errors.New("encryptedData or secretKey is null")}beanValue := reflect.ValueOf(beanPtr)if beanValue.Kind() != reflect.Ptr {return errors.New("传入参数类型必须是以指针形式")}if beanValue.Elem().Kind() != reflect.Struct {return errors.New("传入interface{}必须是结构体")}var (blockcipher.BlockblockMode cipher.BlockModeoriginData []byte)aesKey, _ := base64.StdEncoding.DecodeString(secretKey)ivKey := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}secretData, _ := base64.StdEncoding.DecodeString(encryptedData)if block, err = aes.NewCipher(aesKey); err != nil {return fmt.Errorf("aes.NewCipher:%w", err)}if len(secretData)%len(aesKey) != 0 {return errors.New("encryptedData is error")}blockMode = cipher.NewCBCDecrypter(block, ivKey)originData = make([]byte, len(secretData))blockMode.CryptBlocks(originData, secretData)if len(originData) > 0 {originData = PKCS5UnPadding(originData)}if err = json.Unmarshal(originData, beanPtr); err != nil {return fmt.Errorf("json.Unmarshal(%s):%w", string(originData), err)}return nil}// 解密填充模式(去除补全码) PKCS5UnPadding// 解密时,需要在最后面去掉加密时添加的填充bytefunc PKCS5UnPadding(origData []byte) []byte {length := len(origData)unpadding := int(origData[length-1]) //找到Byte数组最后的填充bytereturn origData[:(length - unpadding)] //只截取返回有效数字内的byte数组}// 根据授权码获取授权信息func GetAliSession(appID, code string) (session *CodeSession, errCode int) {thirdConfigs := user.GetThirdConfigs()_, ok := thirdConfigs[appID]if !ok {return nil, e.InvalidThirdPartAppID}timestamp := time.Now().Format("-01-02 15:04:05")params := map[string]string{"app_id":appID,"code": code,"grant_type": "authorization_code","method":"alipay.system.oauth.token","charset": "utf-8","sign_type": "RSA2","timestamp": timestamp,"version": "1.0",}queryStr := FormatQuery(params)private := config.AliMiniLogin.Privatesign := RsaSignWithSha256(queryStr, private)params["sign"] = signres, err := http.Get(config.AliMiniLogin.Host, params, nil)if res == nil && err != nil {logger.Error("Request Ali AliMiniLogin session Failed:" + err.Error())return nil, e.BUSY}body, err := ioutil.ReadAll(res.Body)if err != nil {return nil, e.BUSY}err = json.Unmarshal(body, &session)if err != nil {return nil, e.BUSY}if session.ErrorResponse.Code != "10000" {return nil, e.BUSY}return session, e.SUCCESS}func FormatQuery(params map[string]string) (queryStr string) {if len(params) == 0 {return}var keys []stringfor k, _ := range params {keys = append(keys, k)}sort.Strings(keys)for _, v := range keys {queryStr += v + "=" + params[v] + "&"}return strings.TrimRight(queryStr, "&")}func RsaSignWithSha256(data string, privateKey string) string {h := sha256.New()h.Write([]byte(data))hashed := h.Sum(nil)privateKey = FormatPrivateKey(privateKey)block, _ := pem.Decode([]byte(privateKey))if block == nil {return ""}priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)if err != nil {return ""}signature, err := rsa.SignPKCS1v15(rand.Reader, priKey, crypto.SHA256, hashed)if err != nil {return ""}return base64.StdEncoding.EncodeToString(signature)}// 私钥验证func ParsePrivateKey(privateKey string) (*rsa.PrivateKey, error) {privateKey = FormatPrivateKey(privateKey)block, _ := pem.Decode([]byte(privateKey))if block == nil {return nil, errors.New("私钥信息错误!")}priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)if err != nil {return nil, err}return priKey, nil}// 组装私钥func FormatPrivateKey(privateKey string) string {if !strings.HasPrefix(privateKey, PEMBEGIN) {privateKey = PEMBEGIN + privateKey}if !strings.HasSuffix(privateKey, PEMEND) {privateKey = privateKey + PEMEND}return privateKey}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。