微信小程序获取手机号,后端JAVA解密流程代码

作者:崔笑颜 时间:2023-11-29 07:57:26 

小程序获取手机号,后端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.df.detection.controller;

import com.df.detection.base.entity.ResultBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.apache.commons.codec.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 = "https://api.weixin.qq.com/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 = json.getString("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 = json.getString("phoneNumber");
     System.out.println("phoneNumber:" + phoneNumber);
     return ResultBean.success("手机号", phoneNumber);
   }
   return ResultBean.error(500,"session_key:失败");
 }
}

工具类代码如下


package com.df.detection.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.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 所代表远程资源的响应结果
    */
   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)");
       // 建立实际的连接
       connection.connect();
       // 获取所有响应头字段
       Map<String, List<String>> map = connection.getHeaderFields();
       // 遍历所有的响应头字段
       for (String key : map.keySet()) {
         System.out.println(key + "--->" + map.get(key));
       }
       // 定义 BufferedReader输入流来读取URL的响应
       in = new BufferedReader(new InputStreamReader(
           connection.getInputStream()));
       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 PrintWriter(conn.getOutputStream());
       // 发送请求参数
       out.print(param);
       // flush输出流的缓冲
       out.flush();
       // 定义BufferedReader输入流来读取URL的响应
       in = new BufferedReader(
           new InputStreamReader(conn.getInputStream()));
       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.df.detection.controller;

import org.apache.tomcat.util.codec.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;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.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 = Cipher.getInstance("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 = AlgorithmParameters.getInstance("AES");
   params.init(new IvParameterSpec(iv));
   return params;
 }

}

接口返回对象ResultBean定义工具类 防止有些朋友发现没有这个类


package com.df.detection.base.entity;

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) {
   this.code = code;
 }

public String getMessage() {
   return message;
 }

public void setMessage(String message) {
   this.message = message;
 }

public T getData() {
   return data;
 }

public void setData(T data) {
   this.data = data;
 }

public String getToken() {
   return token;
 }

public void setToken(String token) {
   this.token = token;
 }
}

来源:https://cloud.tencent.com/developer/article/1663626

标签:Java,微信小程序,获取手机号
0
投稿

猜你喜欢

  • SpringBoot获取配置文件内容的几种方式总结

    2023-11-24 18:10:48
  • 源码浅析Android中内存泄漏检测工具Leakcanary的使用

    2021-11-02 12:30:11
  • springboot整合nacos,如何读取nacos配置文件

    2022-12-30 19:55:25
  • Android 开发中Volley详解及实例

    2023-07-21 00:12:19
  • Unity实现聊天室功能

    2023-12-20 19:53:34
  • 深入理解Java设计模式之装饰模式

    2021-11-23 11:29:52
  • Android AS为xutils添加依赖过程图解

    2023-11-16 03:51:05
  • Unity的OnOpenAsset实用案例深入解析

    2021-05-30 01:37:16
  • Spring MVC中自定义拦截器的实例讲解

    2023-12-19 05:09:04
  • Android Studio 3.5版本JNI生成SO文件详解

    2022-06-11 19:34:11
  • 详解C#实现MD5加密的示例代码

    2023-11-28 21:01:54
  • 详解Java中的反射机制和动态代理

    2023-11-27 15:41:00
  • 关于Java利用反射实现动态运行一行或多行代码

    2021-11-27 23:12:55
  • Android实现多媒体录音笔

    2022-03-26 17:25:00
  • SpringBoot深入分析讲解监听器模式上

    2022-06-25 21:04:04
  • 给C语言初学者的学习建议

    2023-06-14 17:23:44
  • C# 中使用正则表达式匹配字符的含义

    2023-11-19 02:59:38
  • C#+EmguCV使用摄像头读取、保存视频

    2023-01-25 12:20:37
  • Java调用groovy实现原理代码实例

    2023-05-16 16:41:51
  • 教大家使用java实现顶一下踩一下功能

    2021-08-08 21:31:15
  • asp之家 软件编程 m.aspxhome.com