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

(0)

相关推荐

  • 微信小程序后端(java)开发流程的详细步骤

    微信小程序后端开发流程根据官网总结为两个步骤 1.前端调用 wx.login 返回了code,然后调用wx.getUserInfo获取到用户的昵称 头像 2.服务端根据code去微信获取openid, 接口地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html%EF%BC%9B%E5%90%8C%E6%97%B6%EF%BC%8C%E6%9B%B4

  • 微信小程序登录状态java后台解密

    一.登录流程图 二.微信小程序端 doLogin:function(callback = () =>{}){ let that = this; wx.login({ success:function(loginRes){ if(loginRes){ //获取用户信息 wx.getUserInfo({ withCredentials:true,//非必填 默认为true success:function(infoRes){ console.log(infoRes,'>>>'); //

  • java与微信小程序实现websocket长连接

    本文实例为大家分享了java与微信小程序实现websocket长连接的具体代码,供大家参考,具体内容如下 背景: 需要在小程序实现地图固定坐标下实时查看消息 java环境 :tomcat7 jdk1.7 1.java websocket 类 package com.qs.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.

  • Java解密微信小程序手机号的方法

    本文实例为大家分享了Java解密微信小程序手机号的具体代码,供大家参考,具体内容如下 第一步:创建AES解密工具类:代码如下 import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySp

  • 微信小程序调用微信登陆获取openid及java做为服务端示例

    一.微信小程序 第一步:调用 wx.login获取code 文档地址 第二步:判断用户是否授权读取用户信息 文档地址 第三步:调用wx.getUserInfo读取用户数据 文档地址 第四步:由于小程序后台授权域名无法授权微信的域名,所以我们只能通过我们自己的服务器去调用微信服务器去获取用户信息,故我们将wx.login获取code 和 wx.getUserInfo 获取的encryptedData与iv 通过wx.request 请求传入后台 服务器返回的数据: 小程序代码: //调用登录接口,

  • 微信小程序+后端(java)实现开发

    前言 现在微信小程序越来越火了,相信不少人都通过各种途径学习过微信小程序或者尝试开发,作者就是曾经由于兴趣了解开发过微信小程序,最终自己的毕业设计也是开发一个微信小程序.所以现在用这篇博客记录我之前开发的一些经验和一些心得吧. 主要内容 springboot后端架构构建 小程序项目构建 小程序api调用 后台resetful接口编写 小程序调用后台接口 免费的https申请 linux下部署上线 微信小程序项目构建 这些基础的东西我就不过多介绍,大家在刚开始开发的时候一般都没有自己的服务器及域名

  • java遇到微信小程序 "支付验证签名失败" 问题解决

    最近在做一个微信小程序项目做到微信支付的时候遇到的一些问题! 详细步骤: 开发前准备(必须) 小程序标识(appid):wx4d4838ebec29b8** 商户号(mch_id):15508070** 商户密钥(key) :wHtQckdfiRBVF7ceGTcSWEEORt6C0D** 我们用微信官方提供的SDK开发 :https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1 下载 SDK完成后 : 开始写我们的程 进入微信

  • java实现微信小程序加密数据解密算法

    一.概述 微信推出了小程序,很多公司的客户端应用不仅具有了APP.H5.还接入了小程序开发.但是,小程序中竟然没有提供Java版本的加密数据解密算法.这着实让广大的Java开发人员蛋疼. 微信小程序提供的加密数据解密算法链接 我们下载的算法示例如下: 木有Java!! 木有Java!! 木有Java!! 那么如何解决这个问题,我们一起来实现Java版本的微信小程序加密数据解密算法. 二.实现Java版本的微信小程序加密数据解密算法 1.创建项目 这里,我们创建一个Maven工程,具体创建步骤略.

  • java实现微信小程序登录态维护的示例代码

    相信不少喜欢开发的朋友都已经知道微信小程序是个什么物种了,楼主也是从小程序内测期间就开始关注,并且也写过几个已经上线的微信小程序.但是基本上都是写的纯前端,最近楼主从后端到前端写一个完整的小程序项目,中间碰到了一些问题,楼主会找一些个人觉得有学习价值的点不定时的拿出来跟大家分享,希望对你有一些帮助. 本次就从最基本的微信小程序登录态维护开始吧.小程序官方api文档里面有对登录态的一个完整的解释,并且有相关的代码.想看详情,可以出门右转:https://mp.weixin.qq.com/debug

  • 微信小程序订阅消息(java后端实现)开发

    订阅消息说明 订阅消息是微信近期新出的一个能力,用来代替原有的模板消息(原有的模板消息即将下线) 订阅消息的功能较模板消息有所提升,"7天"的限制取消,同时有"一次性"和"永久"订阅.(功能上是这样说的,但是实际开发时发现"永久"订阅还是对小程序的服务类目有要求的,客户的小程序只支持"一次性"订阅) 官方通道: 小程序前端:点击进入 小程序服务端:点击进入 开发思路 用户在小程序内触发按钮或进行支付操作时前

  • 微信小程序 支付后台java实现实例

    微信小程序 支付后台java实现实例 前言: 前些天使用 LeanCloud 云引擎写了个小程序的支付相关 以前只做过 APP 支付 这次在小程序支付爬了两天的坑 把代码也分享出来 支付流程: 1.小程序前端获取微信 openId 以及订单号 传给后台 2,后台根据 openId 和订单号进行签名 post 微信统一下单接口 3.后台获取微信返回的xml字符串 解析 二次签名以后返回给前端 4.前端调起支付微信支付 API 先看支付函数: //获取支付信息 @EngineFunction("ge

  • 微信小程序实现获取小程序码和二维码java接口开发

    前言:目前小程序推出了自己的识别码,小程序码,这个圆形的码看起来比二维码好看.本文总结微信小程序的获取小程序码和二维码并生成二维码图片的接口开发.主要内容摘抄自微信小程序的API文档,java接口开发是自己总结开发. 微信小程序API文档:获取二维码 一.简介 通过后台接口可以获取小程序任意页面的二维码,扫描该二维码可以直接进入小程序对应的页面.目前微信支持两种二维码,小程序码(左),小程序二维码(右),如下所示: 二.获取小程序码 目前有两个接口可以生成小程序码,开发者可以根据自己的需要选择合

  • 微信小程序如何连接Java后台

    前端时间有人问我小程序怎么连接后台,这里直接贴代码 在app.js里 // api request request(url, params) { return new Promise((resolve, reject) => { wx.request({ url: baseUrl + url, method: 'POST', data: params, success(res) { console.log(res.data) resolve(res.data) }, fail(res) { co

  • Java微信小程序oss图片上传的实现方法

    先将图片上传到服务器,再将服务器上的图片传入oss中 小程序js //启动上传等待中... wx.showToast({ title: '正在上传...', icon: 'loading', mask: true, duration: 10000 }) //上传图片 wx.uploadFile({ url: '***********',//上传的路径(Java后台路径) filePath: tempFilePaths[0], name: 'file', success: function (re

  • Java中基于Shiro,JWT实现微信小程序登录完整例子及实现过程

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html : 本文是对接微信小程序自定义登录的一个完整例子实现 ,技术栈为 : SpringBoot+Shiro+JWT+JPA+Redis. 如果对该例子比较感兴趣或者觉得言语表达比较啰嗦,可查看完整的项目地址 : https://github.com/EalenXie/shiro-jwt-applet

随机推荐