java获取微信绑定的手机号码

微信官方文档: https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html.

废话不多说,直接上代码

WeChatPhoneDTO

@Data
public class WeChatPhoneDTO {
    //包括敏感数据在内的完整用户信息的加密数据
    private String encryptedData;
    //加密算法的初始向量
    private String iv;
    //会话密钥
    private String sessionKey;
    //用户openId
    private String openId;
}

Controller

 @GetMapping("/phone")
    public ResponseResult getPhone(WeChatPhoneDTO weChatPhoneDTO) {
        ResponseResult phone = insuranceWeChatService.getPhone(weChatPhoneDTO);
        return phone;
    }

Serviceimpl

@Override
    public ResponseResult getPhone(WeChatPhoneDTO weChatPhoneDTO) {
        AESForWeixinGetPhoneNumber aes=new AESForWeixinGetPhoneNumber(weChatPhoneDTO.getEncryptedData(),weChatPhoneDTO.getSessionKey(),weChatPhoneDTO.getIv());

        WeixinPhoneDecryptInfo info = aes.decrypt();

        if (info != null){
            if (!info.getWeixinWaterMark().getAppid().equals(Constant.APP_ID)){
                log.error("错误的appId{}",Constant.APP_ID);
            }
            //根据openId查询数据
            InsuranceMemberDO dto = insuranceMemberDao.getListByOpenId(weChatPhoneDTO.getOpenId());
            if (dto != null){
                if (dto.getPhone() == null || !dto.getPhone().equals(info.getPhoneNumber())){
                    //如果数据库的电话和解码的电话不同,根据openId将手机号码保存进去
                    Map<String,Object> map = new HashMap<>();
                    map.put("phone",info.getPhoneNumber());
                    map.put("openId",weChatPhoneDTO.getOpenId());
                    insuranceMemberDao.updateByOpenId(map);
                }
                dto.setPhone(info.getPhoneNumber());
            }
            return new ResponseData<>(CommonCode.SUCCESS, dto);
        }
        return null;
    }

WeixinPhoneDecryptInfo

/**
 * @description: 微信手机号信息解密后的对象
 * @author: wrt
 */
public class WeixinPhoneDecryptInfo {
    private String phoneNumber;
    private String purePhoneNumber;
    private int countryCode;
    private String watermark;
    private WeixinWaterMark weixinWaterMark;

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getPurePhoneNumber() {
        return purePhoneNumber;
    }

    public void setPurePhoneNumber(String purePhoneNumber) {
        this.purePhoneNumber = purePhoneNumber;
    }

    public int getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(int countryCode) {
        this.countryCode = countryCode;
    }

    public String getWatermark() {
        return watermark;
    }

    public void setWatermark(String watermark) {
        this.watermark = watermark;
        this.weixinWaterMark = JSON.toJavaObject(JSON.parseObject(this.watermark),WeixinWaterMark.class);
    }

    public WeixinWaterMark getWeixinWaterMark(){
        return weixinWaterMark;
    }

    @Override
    public String toString() {
        return "WeixinPhoneDecryptInfo{" +
                "phoneNumber='" + phoneNumber + '\'' +
                ", purePhoneNumber='" + purePhoneNumber + '\'' +
                ", countryCode=" + countryCode +
                ", appid=" + weixinWaterMark.getAppid() +
                ", timestamp=" + weixinWaterMark.getTimestamp() +
                '}';
    }
}

AESForWeixinGetPhoneNumber

public class AESForWeixinGetPhoneNumber {

    //加密方式
    private static String keyAlgorithm = "AES";
    //避免重复new生成多个BouncyCastleProvider对象,因为GC回收不了,会造成内存溢出
    //只在第一次调用decrypt()方法时才new 对象
    private static boolean initialized = false;
    //用于Base64解密
    private Base64.Decoder decoder = Base64.getDecoder();

    //待解密的数据
    private String originalContent;
    //会话密钥sessionKey
    private String encryptKey;
    //加密算法的初始向量
    private String iv;

    public AESForWeixinGetPhoneNumber(String originalContent,String encryptKey,String iv) {
        this.originalContent = originalContent;
        this.encryptKey = encryptKey;
        this.iv = iv;
    }

    /**
     * AES解密
     * 填充模式AES/CBC/PKCS7Padding
     * 解密模式128
     *
     * @return 解密后的信息对象
     */
    public WeixinPhoneDecryptInfo decrypt() {
        initialize();
        try {
            //数据填充方式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            Key sKeySpec = new SecretKeySpec(decoder.decode(this.encryptKey), keyAlgorithm);
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(decoder.decode(this.iv)));
            byte[]data = cipher.doFinal(decoder.decode(this.originalContent));
            String datastr = new String(data, StandardCharsets.UTF_8);
            return JSON.toJavaObject(JSON.parseObject(datastr),WeixinPhoneDecryptInfo.class);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
    }

    /**BouncyCastle作为安全提供,防止我们加密解密时候因为jdk内置的不支持改模式运行报错。**/
    private static void initialize() {
        if (initialized)
            return;
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }

    // 生成iv
    private static AlgorithmParameters generateIV(byte[] iv) throws NoSuchAlgorithmException, InvalidParameterSpecException {
        AlgorithmParameters params = AlgorithmParameters.getInstance(keyAlgorithm);
        params.init(new IvParameterSpec(iv));
        return params;
    }
}
A: 首先,要使用微信的登录能力,需要注册并开通微信开放平台。具体可以参考微信开放平台的文档。 其次,在开发者工具中创建一个小程序获取小程序的 appID。 然后,在小程序中引入开放能力模块,调用 wx.login 接口获取登录凭证 code。 在获取到 code 后,可以通过微信提供的云开发服务或者自行搭建后台服务器,调用微信的接口换取用户手机号。 下面是一个通过云开发服务获取手机号的例子: ```java import com.tencent.cloud.CosStsClient; import com.tencent.cloud.auth.Credential; import com.tencent.cloud.auth.Credentials; import com.tencent.cloud.auth.ShortTimeCredential; import com.tencent.cloud.CosXmlService; import com.tencent.cloud.CosXmlServiceConfig; import com.tencent.cloud.CosXmlServiceException; import com.tencent.cloud.auth.ScopeLimitCredentialProvider; import com.tencent.cloud.CosXmlSignSourceProvider; import com.tencent.cloud.QCloudSignSourceProvider; import com.tencent.cloud.CosXmlSignSourceProvider.GetSignSourceType; import com.tencent.qcloud.core.auth.COSXmlSignSourceProvider; import com.tencent.qcloud.core.auth.ShortTimeCredentialProvider; import java.util.LinkedList; import java.util.List; public class WeChat { public static void main(String[] args) throws Exception { String appId = "你的小程序的appID"; String appSecret = "你的小程序的appSecret"; String jsCode = "获取到的登录凭证code"; String sessionKey = getSessionKey(appId, appSecret, jsCode); String encryptedData = "获取到的encryptedData"; String iv = "获取到的iv"; String phoneNumber = getPhoneNumber(appId, sessionKey, encryptedData, iv); System.out.println("用户绑定手机号为:" + phoneNumber); } public static String getSessionKey(String appId, String appSecret, String jsCode) throws Exception { String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + jsCode + "&grant_type=authorization_code"; String response = HttpUtils.sendGet(url); JSONObject jsonObject = JSONObject.parseObject(response); String sessionKey = jsonObject.getString("session_key"); return sessionKey; } public static String getPhoneNumber(String appId, String sessionKey, String encryptedData, String iv) throws Exception { String appIdKey = appId + "_session_key"; String appSecretKey = appId + "_session_secret"; String bucketName = "default-bucket-name"; String regionName = "region"; String secretId = "secretId"; String secretKey = "secretKey"; String token = ""; long durationSeconds = 1800; // 创建临时密钥 Credential cred = new Credential(secretId, secretKey); ScopeLimitCredentialProvider scopeLimitCredentialProvider = new ScopeLimitCredentialProvider(new ShortTimeCredentialProvider(cred, durationSeconds), "selected resource regionName", "selected resource bucketName", "selected resource prefix"); LinkedList<String> headers = new LinkedList<String>(); headers.add("host"); headers.add("content-type"); CosStsClient client = new CosStsClient(scopeLimitCredentialProvider); JSONObject credentials = client.getCredential(headers); String token = credentials.getString("sessionToken"); Credentials cred = new Credentials(credentials.getLong("startTime"), credentials.getLong("expiredTime"), credentials.getString("tmpSecretId"), credentials.getString("tmpSecretKey"), token); // 创建 CosXmlServiceConfig 对象,根据个人需求修改默认的配置参数 CosXmlServiceConfig serviceConfig = new CosXmlServiceConfig.Builder() .setAppidAndRegion(appId, regionName) .setDebuggable(true) .builder(); // 创建 CosXmlService 对象,实现获取短期证书的请求签名 CosXmlService cosXmlService = new CosXmlService(context, serviceConfig, new GetSignSourceType() { @Override public QCloudSignSourceProvider getSourceProvider() { return new CosXmlSignSourceProvider(cred); } }); byte[] sessionKeyByte = Base64.decode(sessionKey, Base64.DEFAULT); byte[] encryptedDataByte = Base64.decode(encryptedData, Base64.DEFAULT); byte[] ivByte = Base64.decode(iv, Base64.DEFAULT); // AES解密 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); SecretKeySpec keySpec = new SecretKeySpec(sessionKeyByte, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(ivByte); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); byte[] dataByte = cipher.doFinal(encryptedDataByte); String data = new String(dataByte, "UTF-8"); JSONObject jsonObject = JSONObject.parseObject(data); String phoneNumber = jsonObject.getString("phoneNumber"); return phoneNumber; } } ``` 需要注意的是,在调用云开发服务时,需要引入对应的 SDK 依赖。具体可以参考腾讯云 COSXML SDK 的文档。 另外,由于微信的登录接口比较敏感,开发者在开发时需要注意保护用户的隐私信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值