【2021-11】SpringBoot 后台 获取 微信小程序 用户手机号 sessionKey openID步骤

1、wxml使用getPhoneNumber

<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取用户手机号</button>

在这里插入图片描述
2、js向后台发起请求

注意这里要在发起wx.request给后台解密之前使用wx.login接口更新code(用于解密SessionKey),防止code过期,得到的SessionKey也是过期的,再拿去解密手机号会报错pad block corrupted。最好在每次获取手机号前先使用wx.login更新code。

Page({
  data: {
    code: "",//用于解密session_key和openid的code
    phoneNumber:""
  },
  onLoad:function(e){
    wx.login({
      success:res=>{
        this.setData({
          code:res.code
        })
      }
    })
  },
  getPhoneNumber(e){
    //如果用户允许获取手机号则返回的数组长度为4
    if(Object.getOwnPropertyNames(e.detail).length>1){
      //检查code是否过期,如果过期更换新的code
      wx.checkSession({
        success: (res) => {
          wx.login({
            success:res=>{
              this.setData({
                code:res.code
              })
            }
          })
        },
      })
      //发起解密手机号请求
      wx.request({
        url: '后台连接',
        method: 'POST',
        data: {
          code:this.data.code,
          iv:e.detail.iv,
          encryptedData:e.detail.encryptedData
        },
        header: {
          'content-type': 'application/x-www-form-urlencoded'
        },
        success(res){//控制台打印解密后的手机号
          console.log(res.data)
        }
      })
    }
  }
})

3、SpringBoot获取手机号接口

pom.xml:

<dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.59</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

OpenIdAndSessionKey:

public class OpenIdAndSessionKey {
    private String openid;
    private String session_key;

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }

    public String getSession_key() {
        return session_key;
    }

    public void setSession_key(String session_key) {
        this.session_key = session_key;
    }
}

UserLoginController:

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.test.utils.AESUtil;
import com.test.utils.GetSessionKeyAndOpenId;
import org.springframework.web.bind.annotation.*;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidParameterSpecException;

@RestController
public class UserLoginController {

    /*获取用户的openid*/
    @PostMapping("/user/login/getOpenId")
    public String getOpenId(@RequestParam("code")String code) throws IOException {
        return new GetSessionKeyAndOpenId().getOpenIdAndSessionKey(code).getOpenid();
    }

    /*获取用户的手机号*/
    @PostMapping("/user/login/getPhoneNumber")
    public String getPhoneNumber(@RequestParam("code")String code,
                                 @RequestParam("iv")String iv,
                                 @RequestParam("encryptedData")String encryptedData)
            throws IOException, InvalidParameterSpecException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
        String sessionKey = new GetSessionKeyAndOpenId().getOpenIdAndSessionKey(code).getSession_key();
        JSONObject jsonObject = AESUtil.decrypt(encryptedData,sessionKey,iv);
        return jsonObject.get("phoneNumber").toString();
    }
}

AESUtil:

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;

import static javax.crypto.Cipher.*;

public class AESUtil {

    private static final String KEY_NAME = "AES";

    public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";

    //生成iv
    public static AlgorithmParameters generateIV(byte[] iv)
            throws NoSuchAlgorithmException, InvalidParameterSpecException {
        AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(KEY_NAME);
        algorithmParameters.init(new IvParameterSpec(iv));
        return algorithmParameters;
    }

    //初始化秘钥
    public static void init() throws NoSuchAlgorithmException {
        Security.addProvider(new BouncyCastleProvider());
        KeyGenerator.getInstance(KEY_NAME).init(128);
    }

    //生成解密
    public static JSONObject decrypt(String encryptedData, String sessionKey, String iv)
            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidParameterSpecException {

        byte[] encrypted64 = Base64.decodeBase64(encryptedData.getBytes());
        byte[] session64 = Base64.decodeBase64(sessionKey.getBytes());
        byte[] iv64 = Base64.decodeBase64(iv.getBytes());

        init();

        AlgorithmParameters algorithmParameters = generateIV(iv64);
        Key key = new SecretKeySpec(session64,KEY_NAME);
        Cipher cipher = getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE,key,algorithmParameters);

        String json = new String(cipher.doFinal(encrypted64));
        return JSONUtil.parseObj(json);
    }
}

GetSessionKeyAndOpenId:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.model.OpenIdAndSessionKey;

import java.io.IOException;

public class GetSessionKeyAndOpenId {
    private String appID = "自己的appID";
    private String appSecret = "自己的appSecret";

    public OpenIdAndSessionKey getOpenIdAndSessionKey(String code) throws IOException {
        String result = "";
        try{
            result = HttpUtil.doGet(
                    "https://api.weixin.qq.com/sns/jscode2session?"
                            + "appid=" + this.appID
                            + "&secret=" + this.appSecret
                            + "&js_code=" + code
                            + "&grant_type=authorization_code",null);
        } catch (
                IOException e) {
            e.printStackTrace();
        }
        ObjectMapper mapper = new ObjectMapper();
        OpenIdAndSessionKey openIdJson = mapper.readValue(result, OpenIdAndSessionKey.class);
        return openIdJson;
    }
}

HttpUtil:

import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.HttpStatus;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HttpUtil {
    /*通过请求url连接和参数获取返回的内容并转为string*/
    public static String doGet(String urlPath, HashMap<String,Object> params) throws IOException {
        StringBuilder sb = new StringBuilder(urlPath);
        //在请求的URL后面添加参数,用&分隔
        if(params!=null && !params.isEmpty()){
            sb.append("?");
            Set<Map.Entry<String, Object>> set = params.entrySet();
            for(Map.Entry<String,Object> entry:set){
                String key = entry.getKey();
                String value = "";
                if(null!=entry.getValue()){
                    value = entry.getValue().toString();
                    value = URLEncoder.encode(value,"UTF-8");
                }
                sb.append(key).append("=").append(value).append("&");
            }
            sb.deleteCharAt(sb.length()-1);
        }
        URL url = new URL(sb.toString());
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setConnectTimeout(5000);//超时时间
        conn.setRequestMethod("GET");
        if(conn.getResponseCode()== HttpStatus.SC_OK){
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            StringBuilder sbs = new StringBuilder();
            String line;
            while ((line=reader.readLine())!=null){
                sbs.append(line);
            }
            return sbs.toString();
        }
        return null;
    }
}

参考文章1
https://www.jianshu.com/p/c80979950ce6?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

参考文章2:https://developers.weixin.qq.com/community/develop/doc/0004a8dfe288605a5188675c456000

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现微信、手机号登陆可以分为以下几步: 1. 微信登陆 在前端页面中,使用微信提供的登录接口获取用户的微信授权信息,包括用户openIDsessionKey等。将这些信息发送到后台后台通过验证微信服务器返回的信息,获取用户的唯一标识openID,再将openID与自己的用户系统进行关联,实现微信登录。 2. 手机号登陆 在前端页面中,用户输入手机号和验证码,将这些信息发送到后台后台通过验证手机号和验证码的正确性,再将手机号与自己的用户系统进行关联,实现手机号登录。 3. 微信小程序获取手机号授权用户登录功能和注册功能 在微信小程序中,可以使用微信提供的getUserInfo接口获取用户信息,包括昵称、头像、性别等,但是获取手机号需要用户授权。可以使用微信提供的getPhoneNumber接口获取用户手机号码,但是需要先获取用户授权。具体步骤如下: a. 在小程序中引入wx.login接口,获取用户的code。 b. 将code发送到后台后台通过code向微信服务器获取session_keyopenid。 c. 在小程序中引入wx.getSetting接口,获取用户是否授权手机号的状态。 d. 如果用户未授权,可以使用wx.authorize接口向用户发起授权请求,获取用户手机号。 e. 如果用户已授权,可以使用wx.getUserInfo接口获取用户信息,包括手机号。 f. 将获取到的手机号和其他信息发送到后台后台进行用户注册或登录操作。 注意事项: 1. 在获取用户手机号之前,需要先获取用户授权。 2. 在用户授权之前,需要向用户说明获取手机号的目的和使用方式。 3. 在用户授权之后,需要保护用户的个人隐私,不得将用户手机号用于其他非法用途。 4. 尽可能减少用户的操作次数,提高用户体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值