java---微信小程序用户授权手机号与解密

小程序获取手机号前提:需要有一个非个人的开发者账号,且完成该小程序的认证(不包含海外主体)。建议从现有的公众号平台直接关联小程序,这样就省得再花300元去微信认证一波。当然如果没有那么可以忽略我刚刚说的话。

1.调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器,在服务器端调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key。
public Map<String,Object> oauth2GetOpenid(String code) {
		String GetPageAccessTokenUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=CODE&grant_type=authorization_code";
        String requestUrl = GetPageAccessTokenUrl.replace("APPID", “xxxxx”).replace("SECRET", "xxxxxxx").replace("CODE", code);
        HttpClient client = null;
        Map<String,Object> result =new HashMap<String,Object>();
        try {
            client = HttpClientBuilder.create().build();
            HttpGet httpget = new HttpGet(requestUrl);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            String response = client.execute(httpget, responseHandler);
            net.sf.json.JSONObject OpenidJSONO=net.sf.json.JSONObject.fromObject(response);
            String openid =String.valueOf(OpenidJSONO.get("openid"));
            String session_key=String.valueOf(OpenidJSONO.get("session_key"));
            String unionid=String.valueOf(OpenidJSONO.get("unionid"));
            String errcode=String.valueOf(OpenidJSONO.get("errcode"));
            String errmsg=String.valueOf(OpenidJSONO.get("errmsg"));
            result.put("openid", openid);
            result.put("sessionKey", session_key);
            result.put("unionid", unionid);
            result.put("errcode", errcode);
            result.put("errmsg", errmsg);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            client.getConnectionManager().shutdown();
        }
        return result;
    }
2.根据会话id和敏感数据密文以及偏移量解密数据
public JSONObject decryptData(String sessionKey,String encryptedData, String iv) throws Exception{
        byte[] dataByte = Base64.decodeBase64(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.decodeBase64(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decodeBase64(iv);
        try {
            // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding","BC");
            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, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

注意点

1.需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。

2.需要将 button 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,可以通过 getphonenumber 事件回调获取到微信服务器返回的加密数据, 然后在第三方服务端结合 session_key 以及 app_id 进行解密获取手机号。

<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber"></button>

调试时出现的问题

1.pad block corrupted ==》 我这边出现这个问题是因为解密和加密时的秘钥不一致,解决方式为:在调用wx.login()方法时,先用wx.checkSession()方法判断秘钥是否过期,若过期则重新请求,否则继续用之前的秘钥

参考

java版微信小程序AES加解密敏感数据获取手机号
获取手机号微信官方文档

若有不对的地方,欢迎各位大佬指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值