失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 微信小程序获取用户手机号码 Java后台servlet解密(微信小程序调用微信支付也是大致

微信小程序获取用户手机号码 Java后台servlet解密(微信小程序调用微信支付也是大致

时间:2020-12-04 21:20:43

相关推荐

微信小程序获取用户手机号码 Java后台servlet解密(微信小程序调用微信支付也是大致

本篇记录说明

微信小程序获取用户手机号码,Java后台servlet解密(微信小程序调用微信支付也是大致的流程,详细内容可私信交流)

(第一次写博客,写得不好的地方见谅,面向新手,大佬请无视,不喜勿喷)

一、前言:

微信小程序有一个获取用户手机号码很便捷的接口,通过getPhoneNumber获取用户的已经绑定微信的手机号码。

现在微信和注重用户体验,必须要用户主动触发才可以。必须使用open-type="getPhoneNumber"的按钮来触发。

二、实现步骤:

1、通过wx.login获取【code】;

2、通过getPhoneNumber获取【encryptedData】、【iv】;(ps:切记第1步和第2步的顺序不能颠倒,先调用wx.login,把wx.login写在onload方法里面;然后再通过getPhoneNumber获取【encryptedData】、【iv】)

3、通过wx.request将【encryptedData】、【iv】 、【code】发送到Java后台;

4、Java后台使用【code】,请求微信后台登录凭证校验接口auth.code2Session,获取【openid】和【sessionKey】返回Java后台;

5、Java后台使用【encryptedData】、【iv】、【sessionKey】解密获取用户手机号返回给微信小程序。(ps:微信给的后台解密示例代码里面没有Java,是的,你没有看错,没有Java。)

三、代码展示

1、小程序代码如下:

(1)getPhoneNumber.wxml

<view class='header'></view><view class='text_view'><text>申请获取以下权限</text></view><view class='content'><text>获得您的信息(手机号码等)</text></view><button class='bottom' type='primary' lang="zh_CN" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号码</button><view class='problem'><text>登陆遇到问题?点此联系客服</text><button class='contact-btn' open-type='contact'>a</button></view><view bindtap="cooperate" class='cooperate-phonenumber'></view>

(2)getPhoneNumber.wxss

page {/* background-color: #eee; */height: 100%;overflow: hidden;}.header {margin: 90rpx 0 90rpx 50rpx;text-align: center;width: 650rpx;height: 300rpx;line-height: 450rpx;}.header image {width: 180rpx;height: 180rpx;}.text_view {width: 750rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;}.content {margin-bottom: 90rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;}.content text {display: block;color: #9d9d9d;margin-top: 40rpx;}.bottom {border-radius: 80rpx;margin: 30rpx 20rpx;font-size: 35rpx;}.problem {width: 50%;display: flex;flex-direction: column;justify-content: center;align-items:center;margin-left: 50%;}.problem text {font-size: 28rpx;/* display: block; */color: #576B95; }.contact-btn {position: absolute;width: 100%;opacity: 0;}.cooperate-phonenumber {width: 100%;position: fixed;bottom:20rpx;display: flex;/* margin-top: 30%; */flex-direction: column;justify-content: center;align-items:center;/* margin-left: 50%; */}.cooperate-phonenumber text {font-size: 28rpx;/* display: block; */color: #576B95; }

(3)getPhoneNumber.js

// src/pages/getPhoneNumber/getPhoneNumber.jsPage({/*** 页面的初始数据*/data: {},/*** 生命周期函数--监听页面加载*/onLoad: function(options) {//获取openidwx.login({success(res) {//获取登录凭证console.log("res.conde:" + res.code)try {wx.setStorageSync('code', res.code)} catch (e) {}}})},/*** 生命周期函数--监听页面初次渲染完成*/onReady: function() {},/*** 生命周期函数--监听页面显示*/onShow: function() {},getPhoneNumber(e) {console.log(e)console.log("e.detail.errMsg:" + e.detail.errMsg)console.log("e.detail.iv:" + e.detail.iv)console.log("e.detail.encryptedData:" + e.detail.encryptedData)var code = wx.getStorageSync('code')console.log("conde:" + code)wx.request({url: 'java后台servlet链接',method: "POST",data: {encryptedData: e.detail.encryptedData,iv: e.detail.iv,code: code,},header: {"Content-Type": "application/x-www-form-urlencoded"},success: function(data) {console.log('data:' + data.data)},fail: function() {console.log('request请求错误')},})},/*** 生命周期函数--监听页面隐藏*/onHide: function() {},/*** 生命周期函数--监听页面卸载*/onUnload: function() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh: function() {},/*** 页面上拉触底事件的处理函数*/onReachBottom: function() {},/*** 用户点击右上角分享*/onShareAppMessage: function() {}})

2、Java后台servlet代码如下:

(1) getPhoneNumberServlet,网络请求用okhttp3

package servlet;import java.io.DataOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.math.BigInteger;import .Socket;import .UnknownHostException;import java.security.MessageDigest;import javax.security.sasl.SaslException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import tools.WXCore;public class getPhoneNumberServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String selStr;InputStream is = null;try {is = request.getInputStream();StringBuilder sb = new StringBuilder();byte[] b = new byte[4096];for (int n; (n = is.read(b)) != -1;) {sb.append(new String(b, 0, n));}selStr = .URLDecoder.decode(sb.toString(), "UTF-8");} catch (IOException e) {e.printStackTrace();return;} finally {if (null != is) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println("selStr:" + selStr);String encryptedData = selStr.substring(selStr.lastIndexOf("encryptedData=") + 14, selStr.lastIndexOf("&iv="));System.out.println("encryptedData:" + encryptedData);String iv = selStr.substring(selStr.lastIndexOf("iv=") + 3, selStr.lastIndexOf("&code="));System.out.println("iv:" + iv);String code = selStr.substring(selStr.lastIndexOf("code=") + 5);System.out.println("code:" + code);OkHttpClient client = new OkHttpClient();Request okrequest = new Request.Builder().url("https://api./sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code").build();try {Response okresponse = client.newCall(okrequest).execute();String responsedata = okresponse.body().string();System.out.println("responsedata:" + responsedata);String openid = responsedata.substring(responsedata.lastIndexOf(":") + 2,responsedata.lastIndexOf("\""));String session_key = responsedata.substring(responsedata.indexOf(":") + 2,responsedata.indexOf("==") + 2);System.out.println("原始的openid:" + openid);System.out.println("原始的session_key:" + session_key);String appId = "wx7xxxxxxxxxxxxxxxxxxxx";WXCore wxcore = new WXCore();String phonenumber = wxcore.decrypt(appId, encryptedData,responsedata_session_key, iv);System.out.println("手机号码:" + phonenumber);response.getWriter().write(openid + "&" + phonenumber);} catch (IOException e) {e.printStackTrace();}}public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}}

(2)AES类、WxPKCS7Encoder类、WXCore类,用于解密,用到的包有:bcprov-jdk15on-1.52.jar,commons-codec-1.6.jar,fastjson-1.2.56.jar

<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk16</artifactId> <version>1.46</version> </dependency><dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.29</version> </dependency>

import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; 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 org.bouncycastle.jce.provider.BouncyCastleProvider; /** * AES加密 */ public class AES { 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) { e.printStackTrace(); } catch (Exception e) { 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; } }

import java.nio.charset.Charset;import java.util.Arrays;/*** 微信小程序加解密*/public class WxPKCS7Encoder {private static final Charset CHARSET = Charset.forName("utf-8");private static final int BLOCK_SIZE = 32;/*** 获得对明文进行补位填充的字节.* * @param count 需要进行填充补位操作的明文字节个数* @return 补齐用的字节数组*/public static byte[] encode(int count) {// 计算需要填充的位数int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);if (amountToPad == 0) {amountToPad = BLOCK_SIZE;}// 获得补位所用的字符char padChr = chr(amountToPad);String tmp = new String();for (int index = 0; index < amountToPad; index++) {tmp += padChr;}return tmp.getBytes(CHARSET);}/*** 删除解密后明文的补位字符* * @param decrypted 解密后的明文* @return 删除补位字符后的明文*/public static byte[] decode(byte[] decrypted) {int pad = decrypted[decrypted.length - 1];if (pad < 1 || pad > 32) {pad = 0;}return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);}/*** 将数字转化成ASCII码对应的字符,用于对明文进行补码* * @param a 需要转化的数字* @return 转化得到的字符*/public static char chr(int a) {byte target = (byte) (a & 0xFF);return (char) target;}}

import mons.codec.binary.Base64;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;/*** 封装对外访问方法*/public class WXCore {private static final String WATERMARK = "watermark";private static final String APPID = "appid";/*** 解密数据* * @return* @throws Exception*/public static String decrypt(String appId, String encryptedData, String sessionKey, String iv) {String result = "";try {AES aes = new AES();byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey),Base64.decodeBase64(iv));if (null != resultByte && resultByte.length > 0) {result = new String(WxPKCS7Encoder.decode(resultByte));JSONObject jsonObject = JSON.parseObject(result);String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID);if (!appId.equals(decryptAppid)) {result = "";}}} catch (Exception e) {result = "";e.printStackTrace();}return result;}}

四、步骤详解:

1、通过wx.login获取【code】;

/*** 生命周期函数--监听页面加载*/onLoad: function(options) {//获取openidwx.login({success(res) {//获取登录凭证console.log("res.conde:" + res.code)try {wx.setStorageSync('code', res.code)} catch (e) {}}})},

2、通过getPhoneNumber获取【encryptedData】、【iv】;(ps:切记第1步和第2步的顺序不能颠倒,先调用wx.login,把wx.login写在onload方法里面;然后再通过getPhoneNumber获取【encryptedData】、【iv】)

getPhoneNumber(e) {console.log(e)console.log("e.detail.errMsg:" + e.detail.errMsg)console.log("e.detail.iv:" + e.detail.iv)console.log("e.detail.encryptedData:" + e.detail.encryptedData)},

3、通过wx.request将【encryptedData】、【iv】 、【code】发送到Java后台;

getPhoneNumber(e) {console.log(e)console.log("e.detail.errMsg:" + e.detail.errMsg)console.log("e.detail.iv:" + e.detail.iv)console.log("e.detail.encryptedData:" + e.detail.encryptedData)var code = wx.getStorageSync('code')console.log("conde:" + code)wx.request({url: 'Java后台servlet链接',method: "POST",data: {encryptedData: e.detail.encryptedData,iv: e.detail.iv,code: code,},header: {"Content-Type": "application/x-www-form-urlencoded"},success: function(data) {console.log('data:' + data.data)},fail: function() {console.log('request请求错误')},})},

4、Java后台使用【code】,请求微信后台登录凭证校验接口auth.code2Session,获取【openid】和【sessionKey】返回Java后台;(ps:本篇中不用到【openid】,后续微信小程序调用微信支付时用到)

(1)新建getPhoneNumberServlet类,获取【encryptedData】、【iv】 、【code】

package servlet;import java.io.DataOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.math.BigInteger;import .Socket;import .UnknownHostException;import java.security.MessageDigest;import javax.security.sasl.SaslException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import tools.WXCore;public class getPhoneNumberServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String selStr;InputStream is = null;try {is = request.getInputStream();StringBuilder sb = new StringBuilder();byte[] b = new byte[4096];for (int n; (n = is.read(b)) != -1;) {sb.append(new String(b, 0, n));}selStr = .URLDecoder.decode(sb.toString(), "UTF-8");} catch (IOException e) {e.printStackTrace();return;} finally {if (null != is) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println("selStr:" + selStr);String encryptedData = selStr.substring(selStr.lastIndexOf("encryptedData=") + 14, selStr.lastIndexOf("&iv="));System.out.println("encryptedData:" + encryptedData);String iv = selStr.substring(selStr.lastIndexOf("iv=") + 3, selStr.lastIndexOf("&code="));System.out.println("iv:" + iv);String code = selStr.substring(selStr.lastIndexOf("code=") + 5);System.out.println("code:" + code);}public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}}

(2)将【code】、【小程序 appId】、【小程序 appSecret】、作为参数,使用okhttp请求微信后台登录凭证校验接口auth.code2Session,获取获取【openid】和【sessionKey】。(ps:本篇中不用到【openid】,后续微信小程序调用微信支付时用到)

package servlet;import java.io.DataOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.math.BigInteger;import .Socket;import .UnknownHostException;import java.security.MessageDigest;import javax.security.sasl.SaslException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import tools.WXCore;public class getPhoneNumberServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String selStr;InputStream is = null;try {is = request.getInputStream();StringBuilder sb = new StringBuilder();byte[] b = new byte[4096];for (int n; (n = is.read(b)) != -1;) {sb.append(new String(b, 0, n));}selStr = .URLDecoder.decode(sb.toString(), "UTF-8");} catch (IOException e) {e.printStackTrace();return;} finally {if (null != is) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println("selStr:" + selStr);String encryptedData = selStr.substring(selStr.lastIndexOf("encryptedData=") + 14, selStr.lastIndexOf("&iv="));System.out.println("encryptedData:" + encryptedData);String iv = selStr.substring(selStr.lastIndexOf("iv=") + 3, selStr.lastIndexOf("&code="));System.out.println("iv:" + iv);String code = selStr.substring(selStr.lastIndexOf("code=") + 5);System.out.println("code:" + code);OkHttpClient client = new OkHttpClient();Request okrequest = new Request.Builder().url("https://api./sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code").build();try {Response okresponse = client.newCall(okrequest).execute();String responsedata = okresponse.body().string();System.out.println("responsedata:" + responsedata);String openid = responsedata.substring(responsedata.lastIndexOf(":") + 2,responsedata.lastIndexOf("\""));String session_key = responsedata.substring(responsedata.indexOf(":") + 2,responsedata.indexOf("==") + 2);System.out.println("原始的openid:" + openid);System.out.println("原始的session_key:" + session_key);} catch (IOException e) {e.printStackTrace();}}public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}}

3、调用WXCore类的decrypt方法,将【appId】、【iv】、【sessionKey】作为参数,对【encryptedData】进行解密,获取手机号码。

package servlet;import java.io.DataOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.math.BigInteger;import .Socket;import .UnknownHostException;import java.security.MessageDigest;import javax.security.sasl.SaslException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import tools.WXCore;public class getPhoneNumberServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String selStr;InputStream is = null;try {is = request.getInputStream();StringBuilder sb = new StringBuilder();byte[] b = new byte[4096];for (int n; (n = is.read(b)) != -1;) {sb.append(new String(b, 0, n));}selStr = .URLDecoder.decode(sb.toString(), "UTF-8");} catch (IOException e) {e.printStackTrace();return;} finally {if (null != is) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println("selStr:" + selStr);String encryptedData = selStr.substring(selStr.lastIndexOf("encryptedData=") + 14, selStr.lastIndexOf("&iv="));System.out.println("encryptedData:" + encryptedData);String iv = selStr.substring(selStr.lastIndexOf("iv=") + 3, selStr.lastIndexOf("&code="));System.out.println("iv:" + iv);String code = selStr.substring(selStr.lastIndexOf("code=") + 5);System.out.println("code:" + code);OkHttpClient client = new OkHttpClient();Request okrequest = new Request.Builder().url("https://api./sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code").build();try {Response okresponse = client.newCall(okrequest).execute();String responsedata = okresponse.body().string();System.out.println("responsedata:" + responsedata);String openid = responsedata.substring(responsedata.lastIndexOf(":") + 2,responsedata.lastIndexOf("\""));String session_key = responsedata.substring(responsedata.indexOf(":") + 2,responsedata.indexOf("==") + 2);System.out.println("原始的openid:" + openid);System.out.println("原始的session_key:" + session_key);String appId = "wx7xxxxxxxxxxxxxxxxxxxx";WXCore wxcore = new WXCore();String phonenumber = wxcore.decrypt(appId, encryptedData,responsedata_session_key, iv);System.out.println("手机号码:" + phonenumber);response.getWriter().write(openid + "&" + phonenumber);} catch (IOException e) {e.printStackTrace();}}public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}}

4、大功告成。

五、运行效果截图:

六、结语

以上就是微信小程序获取用户手机号码,Java后台servlet解密的流程和注意事项;微信小程序调用微信支付也基本是这样的流程,第一次写博客,写得不好的地方见谅,面向新手,大佬请无视,不喜勿喷。

如有疑问或项目开发合作,欢迎私信交流

微信小程序获取用户手机号码 Java后台servlet解密(微信小程序调用微信支付也是大致的流程)

如果觉得《微信小程序获取用户手机号码 Java后台servlet解密(微信小程序调用微信支付也是大致》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。