首页 > 编程语言 > 微信小程序获取手机号,后端JAVA解密流程代码
2020
10-10

微信小程序获取手机号,后端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解密流程代码的详细内容,更多关于微信小程序获取手机号的资料请关注自学编程网其它相关文章!

编程技巧