小程序开发授权获取手机号绑定后台用户
小程序开发授权获取手机号绑定后台用户
前端:
注意事项:
前端获取手机号加密信息后不能再调用wx.login()接口,否则后端解密时大概率报错,小概率成功。
后端:
@Data public class AppletLoginDto { @ApiModelProperty(value = "小程序获取手机号encryptedData") private String encryptedData; @ApiModelProperty(value = "小程序获取手机号iv") private String iv; @ApiModelProperty(value = "小程序登录授权code") private String code; @ApiModelProperty(value = "登录用户名/手机号码-前端忽略") private String username; }
实现类serviceImpl
public TokenUserDTO<SystemUserDTO> login(AppletLoginDto dto) { //校验code if (StringUtils.isNullOrEmpty(dto.getCode())) { throw ServiceErrCodeEnum.WX_ILLEGAL_LOGIN.getException(); } String url = String.format(WechatAPI.WECHAT_LOGIN_URL, appletAppId, appletAppSecret, dto.getCode()); String resultString = RequestUtil.doGet(url); if (StringUtils.isNullOrEmpty(resultString)) { throw ServiceErrCodeEnum.WX_ILLEGAL_LOGIN.getException(); } JSONObject jsonObject = (JSONObject) JSONObject.parse(resultString); if (Objects.isNull(jsonObject)) { throw ServiceErrCodeEnum.WX_ILLEGAL_LOGIN.getException(); } log.info("code:{}", JSON.toJSONString(jsonObject)); String sessionKey = jsonObject.get("session_key") + ""; String openid = jsonObject.get("openid") + ""; String unionId = jsonObject.getString("unionid"); //拿手机号 JSONObject phoneJson = WXUtils.getEncryptedData(dto.getEncryptedData(), sessionKey, dto.getIv()); if (Objects.isNull(phoneJson)) { throw ServiceErrCodeEnum.WX_ILLEGAL_LOGIN.getException(); } log.info("code:{}", JSON.toJSONString(phoneJson)); String phoneNumber = phoneJson.getString("phoneNumber"); if (Objects.isNull(phoneNumber)) { throw ServiceErrCodeEnum.WX_ILLEGAL_LOGIN.getException(); } dto.setUsername(phoneNumber); //查询数据库是否已存在该手机号 SysUser user = userService.findByPhone(phoneNumber); if (Objects.isNull(user)){ //无则注册 RegisterSystemUserDTO registerDTO = RegisterSystemUserDTO.builder() .userName(phoneNumber) .realName(phoneNumber) .phone(phoneNumber) .wechat(phoneNumber) .build(); user = userService.register(registerDTO); } //绑定openid user.setOpenId(openid); userMapper.updateByPrimaryKeySelective(user); //=================自己的业务:生成token================= return null; }
微信解密手机号工具类WXUtils
public class WXUtils { public static JSONObject getEncryptedData(String encryptedData, String sessionkey, String iv) { // 被加密的数据 //注意:第一个是ISO-8859-1,第二个是utf-8 byte[] dataByte = Base64.decode(encryptedData); // 加密秘钥 byte[] keyByte = Base64.decode(sessionkey); // 偏移量 byte[] ivByte = Base64.decode(iv); try { // 如果密钥不足16位,那么就补足.这个if中的内容很重要 int base = 16; if (keyByte.length % base != 0) { int groups = keyByte.length / base + 1; byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyByte, 0, temp, 0, keyByte.length); keyByte = temp; } // 初始化 Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化 byte[] resultByte = cipher.doFinal(dataByte); // log.info("返回字节:{}", resultByte); if (null != resultByte && resultByte.length > 0) { String result = new String(resultByte, "UTF-8"); // log.info("加密解密结果:{}", result); return JSONObject.parseObject(result); } } catch (Exception e) { e.printStackTrace(); // log.error("解密加密信息报错:{}", e.getMessage()); } return null; } }
微信WechatAPI封装类
public class WechatAPI { //获取token请求地址 GET public static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; //发送公众号模板消息地址 POST public static final String TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s"; //获取关注公众号用户的openId列表地址 GET public static final String USER_OPEN_ID_LIST_URL = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s"; //获取用户详情地址 GET public static final String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s"; //获取临时二维码ticket地址 public static final String QR_SCENE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s"; //通过ticket换取二维码地址 public static final String QR_TICKET_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"; //通过公众号的openId获取unionId public static final String GET_UNION_ID_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN"; public static final String WXA_CODE_UNLIMIT_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s"; //获取小程序的登录信息 public static final String WECHAT_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"; //小程序消息推送 public static final String PULL_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=%s"; //文本内容检测接口 public static final String AUTH_CONTENT_CHECK_URL = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=%s"; public static final String AUTH_CONTENT_CHECK_URL2 = "https://api.weixin.qq.com/wxa/servicemarket?access_token=%s"; //图片检测接口 public static final String AUTH_IMG_CHECK_URL = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=%s"; }