项目中需要根据用户的微信获取用的手机号,具体的前后端过程如下:
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;
}
}
本文详细介绍如何在微信小程序中通过前后端交互获取用户的手机号,包括小程序端与后台的交互流程,以及后端如何使用Java代码解析加密的手机号信息。

被折叠的 条评论
为什么被折叠?



