微信小程式一鍵登入獲取手機號
阿新 • • 發佈:2020-07-27
一、前端
1、請求傳送 攜帶 code 到後臺換取 openid。
var that = this; wx.login({ success(res) { console.log(res); var code = res.code wx.request({ url: 'http://localhost/index/users/code2seesion', method: "post", data: { code }, success:function (res) { console.log(res.data.openid); that.setData(res.data); } }) } })
在app.js的onLaunch方法中執行,然後儲存在globalData,儲存data內容 裡面包含 openid 和 session_key 。
二、獲取手機號
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">獲取手機號</button>
getPhoneNumber: function (e) { var that = this; console.log(e.detail.errMsg == "getPhoneNumber:ok"); if (e.detail.errMsg == "getPhoneNumber:ok") { wx.request({ url: 'http://localhost/index/users/decodePhone', data: { encryptedData: e.detail.encryptedData, iv: e.detail.iv, sessionKey: that.data.session_key, uid:"", }, method: "post", success: function (res) { console.log(res); } }) } },
點選後將加密的資訊傳至java後臺進行解密,再進行使用。
二、Java後端解密資料
1、實體類
(1)微信手機號資訊解密後的物件
import com.alibaba.fastjson.JSON; /** * @description: 微信手機號資訊解密後的物件 * @author: wrt */ public class WeixinPhoneDecryptInfo { private String phoneNumber; private String purePhoneNumber; private int countryCode; private String watermark; private WeixinWaterMark weixinWaterMark; public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public String getPurePhoneNumber() { return purePhoneNumber; } public void setPurePhoneNumber(String purePhoneNumber) { this.purePhoneNumber = purePhoneNumber; } public int getCountryCode() { return countryCode; } public void setCountryCode(int countryCode) { this.countryCode = countryCode; } public String getWatermark() { return watermark; } public void setWatermark(String watermark) { this.watermark = watermark; this.weixinWaterMark = JSON.toJavaObject(JSON.parseObject(this.watermark),WeixinWaterMark.class); } public WeixinWaterMark getWeixinWaterMark(){ return weixinWaterMark; } @Override public String toString() { return "WeixinPhoneDecryptInfo{" + "phoneNumber='" + phoneNumber + '\'' + ", purePhoneNumber='" + purePhoneNumber + '\'' + ", countryCode=" + countryCode + ", appid=" + weixinWaterMark.getAppid() + ", timestamp=" + weixinWaterMark.getTimestamp() + '}'; } }
(2)水印物件
public class WeixinWaterMark { private Long timestamp; private String appid; public Long getTimestamp() { return timestamp; } public void setTimestamp(Long timestamp) { this.timestamp = timestamp; } public String getAppid() { return appid; } public void setAppid(String appid) { this.appid = appid; } }
2、解密工具類
import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.InvalidParameterSpecException; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import com.alibaba.fastjson.JSON; import entity.WeixinPhoneDecryptInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class AESForWeixinGetPhoneNumber { //加密方式 private static String keyAlgorithm = "AES"; //避免重複new生成多個BouncyCastleProvider物件,因為GC回收不了,會造成記憶體溢位 //只在第一次呼叫decrypt()方法時才new 物件 private static boolean initialized = false; //用於Base64解密 private Base64.Decoder decoder = Base64.getDecoder(); //待解密的資料 private String originalContent; //會話金鑰sessionKey private String encryptKey; //加密演算法的初始向量 private String iv; public AESForWeixinGetPhoneNumber(String originalContent,String encryptKey,String iv) { this.originalContent = originalContent; this.encryptKey = encryptKey; this.iv = iv; } /** * AES解密 * 填充模式AES/CBC/PKCS7Padding * 解密模式128 * * @return 解密後的資訊物件 */ public WeixinPhoneDecryptInfo decrypt() { initialize(); try { //資料填充方式 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); Key sKeySpec = new SecretKeySpec(decoder.decode(this.encryptKey), keyAlgorithm); // 初始化 cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(decoder.decode(this.iv))); byte[]data = cipher.doFinal(decoder.decode(this.originalContent)); String datastr = new String(data, StandardCharsets.UTF_8); return JSON.toJavaObject(JSON.parseObject(datastr),WeixinPhoneDecryptInfo.class); } catch (Exception e) { System.out.println(e.getMessage()); return null; } } /**BouncyCastle作為安全提供,防止我們加密解密時候因為jdk內建的不支援改模式執行報錯。**/ private static void initialize() { if (initialized) return; Security.addProvider(new BouncyCastleProvider()); initialized = true; } // 生成iv private static AlgorithmParameters generateIV(byte[] iv) throws NoSuchAlgorithmException, InvalidParameterSpecException { AlgorithmParameters params = AlgorithmParameters.getInstance(keyAlgorithm); params.init(new IvParameterSpec(iv)); return params; } }
3、涉及到jar包
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.61</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk16</artifactId> <version>1.46</version> </dependency>
4、測試類
public class AEStest { public static void main(String[] args) { String encryptedData="加密的敏感資料"; String iv="初始向量"; String appId="小程式id"; AESForWeixinGetPhoneNumber aes=new AESForWeixinGetPhoneNumber(encryptedData,sessionKey,iv); WeixinPhoneDecryptInfo info=aes.decrypt(); if (null==info){ System.out.println("error"); }else { if (!info.getWeixinWaterMark().getAppid().equals(appId)){ System.out.println("wrong appId"); } System.out.println(info.toString()); } } }