⼩程序获取⼿机号,后端JAVA解密流程代码⼩程序获取⼿机号,后端JAVA解密流程代码
官⽅⽂档获取⼿机号流程地址,先看下最好⽅便理解下⾯步骤
实现思路,步骤如下
1.前端需先调⽤官⽅wx.login接⼝获取登录凭证code。
2.后端接收code 调⽤官⽅接⼝地址获取⽤户秘钥 sessionKey。
3.前端通过官⽅getPhoneNumber获取encryptedData,iv
4.前端通过参数**【encryptedData】、【iv】、【sessionKey】** 发送请求后端接⼝,解密⽤户⼿机号
⼩程序获取sessionkey详细接⼝⽂档
后端⼯作如下,
1.参数code 解密出sessionKey
{“session_key”:“eF9PAi5P7ZbSaQqkGzEY5g==”,“openid”:“otJ1I4zMSFGDtk7C33O_h6U3IRK8”}
2.参数sessionKey,iv,encryptedData 解密出⼿机号
代码如下:
下⾯⼯具类很全,放⼼代码必须全,良⼼教程。
业务代码Controller
package com.ller;
import com.df.ity.ResultBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import dec.binary.Base64;
import org.json.JSONException;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import org.json.JSONObject;
/**
* @Author Songzhongjin
* @Date 2020/7/15 10:09
* @Version 1.0
*/
@Api(value = "⼩程序登录授权 Controller",tags = {"⼩程序登录授权接⼝"})
@RestController
@RequestMapping("/app")
public class APPController {
/**
* ⼩程序登录获取
* 获取session_key
* @param
* @return
*/
@ResponseBody
@PostMapping("/initWxLogin")
@ApiImplicitParams({
@ApiImplicitParam(name = "js_code", value = "登录时获取的code",paramType = "form", dataType = "string", required = true)
})
public ResultBeaninitWxLogin(@RequestParam(value = "js_code", required = true) String js_code) throws JSONException {
//测试数据code
// js_code = "081ZQ3f91fr9VM1HYdb91y93f91ZQ3fU";
//获取session_key接⼝地址
String wxLoginUrl = "api.weixin.qq/sns/jscode2session";
//接⼝参数
String param = "appid=⼩程序id&secret=⼩程序secret&js_code=" + js_code + "&grant_type=authorization_code";
/
/调⽤获取session_key接⼝请求⽅式get
String jsonString = GetPostUntil.sendGet(wxLoginUrl, param);
System.out.println(jsonString);
//因为json字符串是⼤括号包围,所以⽤JSONObject解析
JSONObject json = new JSONObject(jsonString);
//json解析session_key值
String session_key = String("session_key");
System.out.println("session_key:" + session_key);
//返回给前端
return ResultBean.success("session_key",session_key);
}
/
**
* 解密⼩程序⽤户敏感数据
*
* @param encryptedData 明⽂
* @param iv 加密算法的初始向量
* @param sessionKey ⽤户秘钥
* @return
*/
@ResponseBody
@PostMapping(value = "/decodeUserInfo")
@ApiImplicitParams({
@ApiImplicitParam(name = "encryptedData", value = "包括敏感数据在内的完整⽤户信息的加密数据",paramType = "form", dataType = "string", required = true), @ApiImplicitParam(name = "iv", value = "加密算法的初始向量",paramType = "form", dataType = "string", required = true),
@ApiImplicitParam(name = "sessionKey", value = "⽤户秘钥",paramType = "form", dataType = "string", required = true)
})
public ResultBean decodeUserInfo(@RequestParam(required = true, value = "encryptedData") String encryptedData,
@RequestParam(required = true, value = "iv") String iv,
@RequestParam(required = true, value = "sessionKey") String sessionKey
) throws UnsupportedEncodingException, InvalidAlgorithmParameterException, JSONException {
//AESUtils获取⼿机号解密⼯具类
AESUtils aes = new AESUtils();
//调⽤AESUtils⼯具类decrypt⽅法解密获取json串
byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
//判断返回参数是否为空
if (null != resultByte && resultByte.length > 0) {
String jsons = new String(resultByte, "UTF-8");
System.out.println(jsons);
JSONObject json = new JSONObject(jsons);
//json解析phoneNumber值
String phoneNumber = String("phoneNumber");
System.out.println("phoneNumber:" + phoneNumber);
return ResultBean.success("⼿机号", phoneNumber);
}
(500,"session_key:失败");
}
}
⼯具类代码如下
package com.ller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.URL;
import java.URLConnection;
import java.util.List;
import java.util.Map;
/**
* @Author Songzhongjin
* @Date 2020/7/15 10:37
* @Version 1.0
*/
public class GetPostUntil {
/**
* 向指定URL发送GET⽅法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果js获取json的key和value
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通⽤的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建⽴实际的连接
/
/ 获取所有响应头字段
Map<String, List<String>> map = HeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + (key));
}
// 定义 BufferedReader输⼊流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使⽤finally块来关闭输⼊流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 向指定 URL 发送POST⽅法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通⽤的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两⾏
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new OutputStream());
/
/ 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输⼊流来读取URL的响应
in = new BufferedReader(
new InputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使⽤finally块来关闭输出流、输⼊流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}
AESUtils⼯具类解密⼿机号
package com.ller;
import dec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
pto.BadPaddingException;
pto.Cipher;
pto.IllegalBlockSizeException;
pto.NoSuchPaddingException;
pto.spec.IvParameterSpec;
pto.spec.SecretKeySpec;
l.transform.Result;
import java.security.*;
/**
* @Author Songzhongjin
* @Date 2020/7/15 11:46
* @Version 1.0
*/
public class AESUtils {
public static boolean initialized = false;
/**
* AES解密
* @param content 密⽂
* @return
* @throws InvalidAlgorithmParameterException
* @throws NoSuchProviderException
*/
public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException { initialize();
try {
Cipher cipher = Instance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
byte[] result = cipher.doFinal(content);
return result;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void initialize(){
if (initialized) {
return;
}
Security.addProvider(new BouncyCastleProvider());
initialized = true;
}
//⽣成iv
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = Instance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
}
接⼝返回对象ResultBean定义⼯具类防⽌有些朋友发现没有这个类package com.df.ity;
import io.swagger.annotations.ApiModelProperty;
/**
* @author Liu Yaoguang
* @Classname aaa
* @Description
* @Date 2019/12/06 09:22
*/
public class ResultBean<T> {
@ApiModelProperty(value = "返回码",dataType = "int")
private int code;
@ApiModelProperty(value = "返回描述信息",dataType = "string")
private String message;
@ApiModelProperty(value = "返回数据")
private T data;
@ApiModelProperty(value = "⼝令",dataType = "string")
private String token;
private ResultBean() {
}
public static ResultBean error(int code, String message) {
ResultBean resultBean = new ResultBean();
resultBean.setCode(code);
resultBean.setMessage(message);
return resultBean;
}
public static<T> ResultBean error(int code, String message,T data) {
ResultBean resultBean = new ResultBean();
resultBean.setCode(code);
resultBean.setMessage(message);
resultBean.setData(data);
return resultBean;
}
public static ResultBean success(String message) {
ResultBean resultBean = new ResultBean();
resultBean.setCode(200);
resultBean.setMessage(message);
return resultBean;
}
public static<T> ResultBean success(String message,T data) {
ResultBean resultBean = new ResultBean();
resultBean.setCode(200);
resultBean.setMessage(message);
resultBean.setData(data);
return resultBean;
}
public static ResultBean success(String message,Object data,String token) { ResultBean resultBean = new ResultBean();
resultBean.setCode(200);
resultBean.setMessage(message);
resultBean.setData(data);
resultBean.setToken(token);
return resultBean;
}
public int getCode() {
return code;
}
public void setCode(int code) {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论