微信小程序登录时获取用户手机号

本文详细介绍如何在微信小程序中通过前后端交互获取用户的手机号,包括小程序端与后台的交互流程,以及后端如何使用Java代码解析加密的手机号信息。

项目中需要根据用户的微信获取用的手机号,具体的前后端过程如下:
1>.小程序端请求后台接口,传递授权码code;
2>.后台接口根据code,appid,secret,以及grant_type获取用户openid,session_key信息并返回
3>.小程序调用微信api获取用户敏感信息加密串encryptedData以及偏移量iv将两者以及session_key返回到服务器中
4>.服务器根据敏感信息加密串encryptedData以及偏移量iv,session_key解析用户手机号
具体后台代码的实现过程:
1.引入解密加密串以及httputil的包

 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on 用于解密用户信息 -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.60</version>
        </dependency>
		<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>4.5.2</version>
        </dependency>
         <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-http</artifactId>
            <version>4.5.2</version>
        </dependency>
        

2.编写接受数据dto

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Getter;
import lombok.Setter;

/**
 * @description:获取openid接口返回数据的dto
 * @Author: 
 * @Date: 2019/8/13 0013 14:35
 */
@Setter
@Getter
public class OpenIdDto {

    /**
     * 用户唯一标识
     */
    @JSONField(name = "openid")
    private String openId;

    /**
     * 会话密钥
     */
    @JSONField(name = "session_key")
    private String sessionKey;

    /**
     * 错误码
     * 0 请求成功  -1 系统繁忙 40029 code无效 45011 频率限制
     */
    @JSONField(name = "errcode")
    private String errCode;

    /**
     * 错误信息
     */
    @JSONField(name = "errmsg")
    private String errMsg;

    /**
     * 用户在开放平台的唯一标识符,
     */
    @JSONField(name = "unionid")
    private String unionId;
}

3.编写工具类:

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.ruite.detection.common.tools.wechat.dto.OpenIdDto;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.codec.binary.Base64;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:根据openid获取用户信息
 * @Author: 
 * @Date: 2019/8/13 0013 11:35
 */
@Component
@ConfigurationProperties(value = "wechat", ignoreUnknownFields = false)
@PropertySource(value = "classpath:config/wechat.properties")
public class GetUserInfoByOpenid {

    @Setter @Getter
    private String appId;

    @Setter @Getter
    private String appSecret;

    @Setter @Getter
    private String grantType;

    @Setter @Getter
    private String getOpenIdUrl;

    /**
     * 获取用户openid信息
     * @param code
     * @return
     */
    public Map<String,Object> getOpenId(String code){
        Map<String,Object> params = this.initParamMap(code);
        String result= HttpUtil.get(getOpenIdUrl, params);
        OpenIdDto openIdDto = JSON.parseObject(result,OpenIdDto.class);
        Map<String,Object> resultMap = BeanUtil.beanToMap(openIdDto);
        return resultMap;
    }

    /**
     * 获取加密用户的手机号
     * @param encryptedData 加密串
     * @param sessionKey 会话密钥
     * @param iv 偏移量
     * @return
     */
    public String getUserPhoneNumber(String encryptedData, String sessionKey, String iv){
        String result = this.decrypt(encryptedData,sessionKey,iv,"UTF-8");
        String phoneNumber = (String) JSONUtil.parseObj(result).get("phoneNumber");
        return phoneNumber;
    }

    /**
     * 解密信息
     * 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
     * 对称解密的目标密文为 Base64_Decode(encryptedData)。
     * 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
     * 对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
     * @return
     */
    public String decrypt(String data, String sessionKey, String iv, String encodingFormat){
        // 被加密的数据
        byte[] dataByte = Base64.decodeBase64(data);
        // 加密秘钥
        byte[] keyByte = Base64.decodeBase64(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decodeBase64(iv);
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, encodingFormat);
                return result;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 初始化参数
     * @param code
     * @return
     */
    public Map<String,Object> initParamMap(String code){
        Map<String,Object> map = new HashMap<>();
        map.put("appid",appId);
        map.put("secret",appSecret);
        map.put("js_code",code);
        map.put("grant_type",grantType);
        return map;
    }

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值