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

 更新时间:2020年09月09日 08:33:14   作者:崔笑颜  
这篇文章主要介绍了微信小程序获取手机号,后端JAVA解密流程的代码,帮助大家更好的利用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.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;
  }
}

以上就是微信小程序获取手机号,后端JAVA解密流程代码的详细内容,更多关于微信小程序获取手机号的资料请关注脚本之家其它相关文章!

相关文章

  • Mybatis 如何在配置文件中给实体类起别名

    Mybatis 如何在配置文件中给实体类起别名

    这篇文章主要介绍了Mybatis 如何在配置文件中给实体类起别名的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 利用java实现一个客户信息管理系统

    利用java实现一个客户信息管理系统

    这篇文章主要给大家介绍了关于利用java实现一个客户信息管理系统的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • java 非对称加密算法RSA实现详解

    java 非对称加密算法RSA实现详解

    这篇文章主要介绍了java 非对称加密算法RSA实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Java学习基础之安装JDK/配置JDK环境&IEDA工具安装

    Java学习基础之安装JDK/配置JDK环境&IEDA工具安装

    这篇文章主要介绍了Java学习基础系列文章的第一篇,主要内容是安装JDK/配置JDK环境&IEDA工具安装的相关资料,需要的朋友可以参考下
    2020-02-02
  • Java JDK8新增Optional工具类讲解

    Java JDK8新增Optional工具类讲解

    这篇文章主要介绍了Java JDK8新增Optional工具类讲解,本文通过老版和jdk8对比对null的处理方式,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • Spring Aop基本流程原理示例详解

    Spring Aop基本流程原理示例详解

    这篇文章主要给大家介绍了关于Spring Aop基本流程原理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • java中List集合及其遍历详解

    java中List集合及其遍历详解

    这篇文章主要介绍了java中List集合及其遍历详解的相关资料,需要的朋友可以参考下
    2015-07-07
  • java final 和instanceof 关键字的区别

    java final 和instanceof 关键字的区别

    这篇文章介绍了java final 和instanceof 关键字的区别,有需要的朋友可以参考一下
    2013-09-09
  • Spring事务的开启原理详解

    Spring事务的开启原理详解

    这篇文章主要介绍了Spring事务的简单实现步骤,帮助大家更好的理解和学习使用spring,感兴趣的朋友可以了解下
    2021-03-03
  • Java使用Comparable解决排序问题

    Java使用Comparable解决排序问题

    这篇文章主要介绍了Java使用Comparable解决排序问题的方法,涉及java针对文件的相关操作及排序的技巧,需要的朋友可以参考下
    2015-05-05

最新评论