微信小程序获取用户手机号总结

前言

公司最近开发一个程序,需求是要通过用户手机号去数据库获得CUSTOMERID,根据CUSTOMERID来进行下面的一系列操作。现总结一下经验:

1.授权获取密文

根据微信小程序官方文档的说明,要获取手机号加密密文必须通过button组件的bindgetphonenumber事件回调。因此根据需求不同可以有三种方式授权:

①.首页设为授权页

用户第一次进入小程序先让用户授权,不然无法跳转其他页面,取得CUSTOMERID后存入本地用户下次登录小程序无需再次授权。

授权页

②在登录页获取授权

在登录页设置两个button组件,后台JS的data里面添加布尔变量isLogin,默认为false,后台获得CUSTOMERID后在成功回调函数里面把isLogin设为true,这样两个button组件在授权前后就只会出现一个。

<button wx:if="{{isLogin}}" class="next-step" bindtap="login">下一步</button> 
<button wx:else class="next-step" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">授权</button>

③底部导航栏“我的”

在该页设置登录按钮,这也是大多数小程序采用的方法。
B站登录页
点击授权按钮并且同意之后会获得一大串的加密密文encryptedData和加密算法的初始向量iv如下:

2.获取密钥

利用小程序提供的API中的wx.login方法来获取临时登录凭证 code,然后通过访问微信提供的接口地址来获取密钥session_key。

https://api.weixin.qq.com/sns/jscode2sessionappid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

请求参数
PS:APPID和SECRET的获取链接,登录之后可以查看。
在相应位置填入参数,发送GET请求,成功后会返回session_key。代码如下:

 wx.login({
   success: function (res) {
     wx.request({
       url: 'https://api.weixin.qq.com/sns/jscode2session?appid=wx9*****ff540c64e&secret=3fd147f9e24******738bb84fae30be&js_code=' + res.code + '&grant_type=authorization_code',
       success: function (res) {
         wx.setStorageSync('key', res.data.session_key)
       }
     })
  }
})

PS :并不推荐这样写,官方文档也说了不要把session_key传到前端,应该在自己的服务器中请求API地址,完成解密后返回手机号信息即可。
注意事项

3.解密

解密需要一个依赖类,Maven如下:

<dependency>
   <groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk16</artifactId>
	<version>1.46</version> 
</dependency>

把目前获取到的密文,密钥,初始向量传入后台。

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.Security;
import java.util.Arrays;
import static org.bouncycastle.util.encoders.Base64.decode;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

@RestController
@RequestMapping("/user")
public class UserController {

  	private static final String KEY_ALGORITHM = "AES";
  	private static final String ALGORITHM_STR = "AES/CBC/PKCS7Padding";
  	private static Key key;
  	private static Cipher cipher;
 
	 @RequestMapping("getPhoneNumber")
	  public String getPhoneNumber(String encryptedData,String key,String iv) {
	    String data = decryptData(encryptedData, key, iv);
	    JSONObject jsonObject = JSON.parseObject(data);
    	String phoneNumber = jsonObject.get("phoneNumber").toString();
	    return phoneNumber;
	  }
	  
	  public static String decryptData(String encryptDataB64, String sessionKeyB64, String ivB64) {
	    return new String(
	            decryptOfDiyIV(
	                    decode(encryptDataB64),
	                    decode(sessionKeyB64),
	                    decode(ivB64)
	            )
	    );
	  }
	
	  /**
	   * 解密方法
	   *
	   * @param encryptedData 要解密的字符串
	   * @param keyBytes      解密密钥
	   * @param ivs           自定义对称解密算法初始向量 iv
	   * @return 解密后的字节数组
	   */
	  private static byte[] decryptOfDiyIV(byte[] encryptedData, byte[] keyBytes, byte[] ivs) {
	    byte[] encryptedText = null;
	    init(keyBytes);
	    try {
	      cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs));
	      encryptedText = cipher.doFinal(encryptedData);
	    } catch (Exception e) {
	      e.printStackTrace();
	    }
	    return encryptedText;
	  }
	}

	private static void init(byte[] keyBytes) {
	    // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
	    int base = 16;
	    if (keyBytes.length % base != 0) {
	      int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
	      byte[] temp = new byte[groups * base];
	      Arrays.fill(temp, (byte) 0);
	      System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
	      keyBytes = temp;
	    }
	    // 初始化
	    Security.addProvider(new BouncyCastleProvider());
	    // 转化成JAVA的密钥格式
	    key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
	    try {
	      // 初始化cipher
	      cipher = Cipher.getInstance(ALGORITHM_STR, "BC");
	    } catch (Exception e) {
	      e.printStackTrace();
	    }
	 }

PS:代码参考作者@名字叫孙冉

注意:根据上面的方法获得的解密data数据是json格式字符串,需要再转为JSON对象才能取到里面的phoneNumer
结果如下:
在这里插入图片描述

在这里插入图片描述

  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值