微信小程序获取手机号(Java)
微信小程序官方文档地址 :https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
获取微信用户绑定的手机号,需先调用wx.login接口。
因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。
注意:目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限。
1.WXBizDataCrypt实现类
package com.shucha.deveiface.biz.test;
/**
* @author tqf
* @Description 小程序AES解密工具 获取手机号
* @Version 1.0
* @since 2021-03-29 11:14
*/
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;
import java.util.Base64;
@Data
public class WXBizDataCrypt {
private String appId;
private String sessionKey;
public static void main(String[] args) {
String appId = "wxab1ead30c255c845";
String sessionKey = "ZMD72RbH5jmjjdU/r9K6/Q==";
String encryptedData = "Kt3Jo0HchNf/Jog3WOdVi99AqQOiWmRXgd6MbmAVQHkHAZDtPOEtvxaL/1JSe25REfyYT3WFHa6muHo6I8JXjefZYBRCHA2uB2/Em6GiKjQLXjTKLmq/fwJVZ9FJje0wk9DFnPEiS561We1SsdanxPHhT/Tphga354F5si4s9Eh7xVJo4zZwWGVf9OvFRuQrpbxUnziPNaRB5sP5uacLhg==";
String iv = "UsRFhbsbaDp4BCeaRqmDkg==";
WXBizDataCrypt pc = new WXBizDataCrypt(appId,sessionKey);
JSONObject decrypt = pc.decrypt(encryptedData, iv);
System.out.println(decrypt.toString());
}
public WXBizDataCrypt(String appId, String sessionKey) {
this.appId = appId;
this.sessionKey = sessionKey;
}
/**
* 解密成json
*
* @param encryptedData
* @param iv
* @return
*/
public JSONObject decrypt(String encryptedData, String iv) {
byte[] encryptedDataDecode = Base64.getDecoder().decode(encryptedData);
byte[] sessionKeyDecode = Base64.getDecoder().decode(this.sessionKey);
byte[] ivDecode = Base64.getDecoder().decode(iv);
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] decodeData = decode(encryptedDataDecode, sessionKeyDecode, ivDecode);
String stringData = new String(decodeData);
JSONObject jsonObject = JSONObject.parseObject(stringData);
return jsonObject;
}
/**
* 解密算法 AES-128-CBC
* 填充模式 PKCS#7
*
* @param encryptedDataDecode 目标密文
* @return
* @throws Exception
*/
private byte[] decode(byte[] encryptedDataDecode, byte[] sessionKeyDecode, byte[] iv) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(sessionKeyDecode, "AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(iv));// 初始化
byte[] result = cipher.doFinal(encryptedDataDecode);
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 处理iv
*
* @param iv
* @return
* @throws Exception
*/
private AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
}
2.实际的解密之后的数据
{"phoneNumber":"18556355920","watermark":{"appid":"wxab1ead30c255c845","timestamp":1616988812},"purePhoneNumber":"18556355920","countryCode":"86"}
参数 | 类型 | 说明 |
---|---|---|
phoneNumber | String | 用户绑定的手机号(国外手机号会有区号) |
purePhoneNumber | String | 没有区号的手机号 |
countryCode | String | 区号 |
3.tips遇到的问题
3.1 javax.crypto.BadPaddingException: pad block corrupted
这个可能是请求获取数据和解密的顺序导致,顺序依照4执行。
4.正确的做法应该是:
- 先才调用的wx.login获取code。
- 然后再通过code取到用户的session_key 。
- 再通过getPhoneNumber获取了手机号的加密数据。
- 最后再用session_key,手机号的加密数据和向量解密获取手机号。
改完之后果然就没有问题。
这是因为调用了wx.login后通过code获得的session_key是新的session_key.
所以,在调用wx.login之前获的加密数据不是用新得session_key加密的数据。
在调用wx.login之后获得的加密数据,才是新得的session_key加密的数据。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)