1. 程式人生 > 實用技巧 >微信小程式一鍵登入獲取手機號

微信小程式一鍵登入獲取手機號

一、前端

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());
        }
    }
}