用户优先:确保微信小程序手机号授权在新旧版本中无缝衔接

news2024/9/27 7:16:45

在这里插入图片描述

🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者
📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代
🌲文章所在专栏:微信体系
🤔 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识
💬 向我询问任何您想要的东西,ID:vnjohn
🔥觉得博主文章写的还 OK,能够帮助到您的,感谢三连支持博客🙏
😄 代词: vnjohn
⚡ 有趣的事实:音乐、跑步、电影、游戏

目录

  • 前言
  • 官方介绍
    • 组件 API
    • 付费管理
  • 源码章节
    • 基础配置
      • pom 依赖
      • 微信小程序属性文件
      • 微信小程序配置类
    • 微信授权 API
    • 新版 > 微信手机号获取
    • 旧版 > 微信手机号获取
  • 总结

前言

自 2023年8月28日起,手机号验证组件(无论是快速还是实时验证组件)将进行付费使用,由于微信官方作出的调整,各个业务的小程序不得不跟随着一起进行版本的更新,进行系统的新组件兼容

小程序手机验证组件在个人开发者下是无法使用的,它只提供给那些完成了认证的小程序开发(不包含海外主体)

新规调整,给业务系统留有一段的缓冲时间,它与 6 月份就发表了官方说明,留有两个月时间作出调整,对于前端或全栈的小伙伴来说,应该会第一时间去关注这种重大事项的,为公司所在系统及时作出规划和调整

在新版本出来时,每个小程序账号将有 1000 次体验额度,用于开发、调试和体验,但这 1000 次额度不区分正式版、体验版和开发版,都是共用的,一旦超过了这个额度后,一旦调用额度都要采取收费措施

在这里插入图片描述

新版变更,手机号验证组件区分两种调用方式,手机号快速验证组件、手机号实时验证组件

手机号快速验证组件,平台会对号码进行验证,但不保证是实时验证,每次调用函数成功收费:0.03 元
后即好实时验证组件,在每次请求时,平台均会对用户选择的手机号进行实时验证,每次调用成功收费:0.04 元

官方介绍

手机号快速验证组件:手机号快速验证组件
手机号实时验证组件:手机号实时验证组件

组件 API

快速验证组件与实时验证组件所调用的 API 不同,在考虑企业的成本以及用户手机号信息准确性来适中进行选择

手机号快速验证组件

<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>

手机号实时验证组件

<button open-type="getRealtimePhoneNumber" bindgetrealtimephonenumber="getrealtimephonenumber"></button>

区别在于一个是 getPhoneNumber,一个是 getRealtimePhoneNumber

付费管理

在这里插入图片描述

登录小程序后台以后,在左侧菜单「管理 > 付费管理」进行手机号验证组件的余额、购买查看

在这里插入图片描述

体验额度是没有有效期的,只有小程序认证主体一直存在,这个体验额度是一直会保留的

在这里插入图片描述

快速验证组件选择的有效期越短,所收取的费用就越低,次数也就在有效期的基础上作出适当调整

在这里插入图片描述

实时验证组件选择的有效期越短,所收取的费用就越低,次数也就在有效期的基础上作出适当调整

源码章节

对比很旧的系统来说,相信大家都是使用的那一套解密三个参数「sessionKey、encryptedData、iv」的方法来获取手机号的,解密的方法大致如下所示:

/**
 * AES解密.
 *
 * @param sessionKey    session_key
 * @param encryptedData 消息密文
 * @param ivStr         iv字符串
 */
public static String decrypt(String sessionKey, String encryptedData, String ivStr) {
  try {
    AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
    params.init(new IvParameterSpec(Base64.decodeBase64(ivStr)));

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Base64.decodeBase64(sessionKey), "AES"), params);

    return new String(PKCS7Encoder.decode(cipher.doFinal(Base64.decodeBase64(encryptedData))), UTF_8);
  } catch (Exception e) {
    throw new WxRuntimeException("AES解密失败!", e);
  }
}

若在你的系统中仍然是采用这种方式来获取手机号的,那么在微信新版更新以后,在你的服务端不得不更改代码来进行微信新版的适配了

基础配置

引入服务端最新的 pom 依赖,这是非常重要的一个变更

pom 依赖

在这个依赖的版本中会适配上微信手机号验证组件新规的内容,如下:

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-miniapp</artifactId>
    <version>${binarywang.version}</version>
</dependency>

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-open</artifactId>
    <version>${binarywang.version}</version>
</dependency>

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-mp</artifactId>
    <version>${binarywang.version}</version>
</dependency>

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-common</artifactId>
    <version>${binarywang.version}</version>
</dependency>

以上包括了微信官方公共工具包、微信小程序、微信公众号、微信开放平台的依赖,引入以上的依赖,在我们的服务端内部就能任意的调用方法一样的去远程调用微信的官方 API 了

引入 binarywang 微信依赖的方式,不用我们再到代码中写一大堆的地址配置、AccessToken 认证及保存,它会帮我们再底层进行封装后。然后,对接过微信支付的小伙伴应该也知晓,以前调用微信支付接口的参数和返回的内容都是 XML 方式的,需要我们在项目中再通过 XmlStream 进行 XML 解析成 JSON 格式;最后,一个我喜欢的地方,之前返回的字段命名都是下划线隔开的,不是我熟悉的那种首字母小写驼峰命名规则,所以我们不得不在代码中进行 JSON 序列化时 + 上 @JsonProperty 注解,然而在这个依赖中这些问题都不需要我们考虑,我们只要安心的调用和处理返回的结果即可.

微信小程序属性文件

wx.mini.app.appId=xx
wx.mini.app.secret=xx
# 开发版
#wx.mini.app.envVersion=develop
# 体验版
#wx.mini.app.envVersion=trial
# 生产版
wx.mini.app.envVersion=release
wx.mini.app.homePagePath=pages/index/index

微信小程序配置类

/**
 * @author vnjohn
 * @since 2023/7/11
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "wx.mini.app")
@PropertySource(value ={"classpath:wx-mini-app.properties"})
public class WxMaConfiguration {
    private String appId;

    private String secret;

    private String envVersion;

    private String homePagePath;

    private static WxMaService WX_MA_SERVICE = null;
    public static String WX_APP_ID;
    public static String ENV_VERSION;
    public static String HOME_PAGE_PATH;

    public static WxMaService getWxMaService() {
        return WX_MA_SERVICE;
    }

    @PostConstruct
    public void init() {
        WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
        config.setAppid(appId);
        config.setSecret(secret);
        WxMaService service = new WxMaServiceImpl();
        service.setWxMaConfig(config);
        WX_MA_SERVICE = service;
        ENV_VERSION = envVersion;
        WX_APP_ID = appId;
        HOME_PAGE_PATH = homePagePath;
    }
}

在配置类中的初始化方法将微信小程序提供的服务配置类先进行初始化,这是以前我们会调用微信小程序 API 获取 AccessToken 的演变,后续在调用微信 API 时只需要通过调用 getWxMaService 方法即可.

微信授权 API

在进行手机号验证组件源码前,微信授权是小程序用户信息的唯一判别标准,因为在授权接口中会返回 open_id,这个参数代表微信小程序用户的唯一标注,所以先来通过调用它实现结果解析

/**
 * 通过小程序获取的Code 进行微信授权
 *
 * @param code 登录时获取的 code
 * @return WxMaJscode2SessionResult
 */
public WxMaJscode2SessionResult wxAccredit(String code) {
    // 参数校验
    notEmpty(code, ResultMsgCodeEnum.ResultMsgCode.CODE_INVALID);
    WxMaJscode2SessionResult wxMaJscode2SessionResult;
    try {
        // 微信登录
        wxMaJscode2SessionResult = WxMaConfiguration.getWxMaService().getUserService().getSessionInfo(code);
    } catch (WxErrorException e) {
        log.error("wxAccredit 微信授权失败,", e);
        return null;
    }
    log.info("wxAccredit 微信授权 {},", JsonUtils.objToJsonStr(wxMaJscode2SessionResult));
    // 返回信息
    return wxMaJscode2SessionResult;
}

wxAccredit 方法中的 code 参数是前端调用 wx.login 组件进行获取到的,调用实例如下:

wx.login({
  success (res) {
    if (res.code) {
      // 向你的服务端授权接口发起网络请求
      wx.request({
        url: 'https://example.com/onLogin',
        data: {
          code: res.code
        }
      })
    } else {
      console.log('登录失败!' + res.errMsg)
    }
  }
})

通过 wx.login 组件获取到 code 参数后,再调用服务端的微信授权接口,即可实现小程序的微信信息获取,服务端接口请求成功后返回的内容会有这些信息:

@SerializedName("session_key")
private String sessionKey;

@SerializedName("openid")
private String openid;

@SerializedName("unionid")
private String unionid;

sessionKey:参数代表当前会话的微信标识,它的有效期在一个会话内,当微信小程序那边通过组件调用 wx.login 后,该值就会发生改变,这个参数在服务端兼容旧版手机号验证会使用到,一般会在登录接口进行返回作为前端的全局参数以便在后续能够传递进行手机号绑定==

规避一个不好的系统设计:有的旧系统会使用这个参数来作为小程序登录的会话缓存,也就是说登录完成以后,后面所有的请求都通过这个参数值来进行服务端接口的请求,这样存在的问题是,该参数的有效期是由微信那边进行管理的,若你的系统在某些地方由于用户手动将小程序移除掉了或小程序退出超过了静默时间又或者是在某处重新调用了 wx.login,那这个值在微信那边就是属于无效的了,但是你的服务端还仍然在使用这个参数值进行别的请求处理,从而引起的报错你又浪费了很多时间,小程序登录会话值最好是由业务系统自行管理,这点功夫没必要省,后续只会有更多乏而无味的事情等你去收拾

openid:该参数代表当前小程序用户的唯一标识,一般在未认证手机号之前,openid 值就能作为小程序业务端的唯一标识,再说,手机号是可以更换的,若你用手机号作为唯一索引,包不准那天用户就把手机号换了,那你系统里面的信息都看不到了

unionid:该参数在普通的小程序主体下是不会返回的,只有当前主体有开通微信开放平台,并且将小程序绑定到了微信开放平台上,这个值才会在微信授权接口返回

微信小程序、微信公众号两个业务系统,唯一可以识别是同一个用户的,也就是靠这个值来进行区分了

新版 > 微信手机号获取

/**
 * 通过小程序获取 Code 进行微信授权获取手机号
 *
 * @param code 动态令牌
 * @return WxMaPhoneNumberInfo
 */
public WxMaPhoneNumberInfo wxGetPhone(String code) {
    // 参数校验
    notEmpty(code, ResultMsgCodeEnum.ResultMsgCode.CODE_INVALID);
    if (StringUtils.isEmpty(code)) {
        log.info("小程序获取手机号 Code,参数为空");
        return null;
    }
    // 解密手机号信息
    WxMaPhoneNumberInfo phoneNoInfo;
    try {
        phoneNoInfo = WxMaConfiguration.getWxMaService().getUserService().getPhoneNoInfo(code);
    } catch (WxErrorException e) {
        log.error("wxGetPhone 微信获取手机号失败,", e);
        return null;
    }
    log.info("wxGetPhone 微信获取手机号信息 {},", JsonUtils.objToJsonStr(phoneNoInfo));
    // 返回信息
    return phoneNoInfo;
}

在微信新版本获取手机号时,无论是快速还是实时验证组件,对于服务端都是一样的,都是只需要一个参数:code 即可了,返回该 code 在前端是这些进行处理的,源码如下:

快速验证组件

<u-button class="register" type="primary" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
  去授权
</u-button>

实时验证组件

<u-button class="register" type="primary" open-type="getRealtimePhoneNumber" @bindgetrealtimephonenumber="getPhoneNumber">
  去授权
</u-button>

getPhoneNumber 函数的处理过程如下:

// authPhone 是封装的,请求服务端的 API
const getPhoneNumber = (e) =>{
  authPhone({
    authMobileCode: e.detail.code,
    encryptedData: e.detail.encryptedData,
    iv: e.detail.iv,
    sessionKey: userInfo.sessionKey
  }).then(res =>{
    changeStatus()
    if(props.type === 'order') return
    uni.navigateBack()
  })
}

在用户的微信老、新的版本中,返回的参数会有所区别,可能在旧版本的微信中 code 参数是返回空的,此时在授权接口返回的 sessionKey 会话参数就有作用了,配合 encryptedData、iv 参数一起请求后端,进行手机号获取

从这里看出,服务端这块是跟随着小程序规则调整以后都需要进行代码更新的,在微信新版本中,前端只返回了 code 参数,服务端就必须接入 API 处理单个 code 参数获取手机号的业务逻辑

收费取决于在前端运用的组件是哪一种,在手机号验证的入口就已经牢牢给你捆绑住了,前后端都要进行相对应的适配和更新

旧版 > 微信手机号获取

在旧有系统的服务端 API 基于微信旧版本的用户还是仍然可以保留下来的,只是在前面介绍的基础配置中,github 微信组件库为我们提供了更加便利的方式调用,只是参数的变更,其他的返回参数的区别,该方法调用示例如下:

/**
 * 通过小程序 SessionKey、encryptedData、iv 进行解密获取手机号
 *
 * @param sessionKey    – 会话密钥
 * @param encryptedData 消息密文
 * @param iv            加密算法的初始向量
 * @return WxMaPhoneNumberInfo
 */
public WxMaPhoneNumberInfo wxGetPhoneByIv(String sessionKey, String encryptedData, String iv) {
    // 参数校验
    if (StringUtils.isEmpty(sessionKey) || StringUtils.isEmpty(encryptedData) || StringUtils.isEmpty(iv)) {
        log.info("解密获取手机号,参数为空");
        return null;
    }
    // 解密手机号信息
    WxMaPhoneNumberInfo phoneNumberInfo  = WxMaConfiguration.getWxMaService().getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
    log.info("wxGetPhoneByIv 微信获取手机号信息 {},", JsonUtils.objToJsonStr(phoneNumberInfo));
    // 返回信息
    return phoneNumberInfo;
}

微信新版本获取手机号的方法调用 wxGetPhone 方法即可,微信旧版本获取手机号的方法调用 wxGetPhoneByIv 方法即可.

在这里插入图片描述

从组件库源码中,发现该方法已经被丢弃,但是并不影响我们进行调用,我们仍然需要这种方式去进行微信旧版本的兼容处理!!

总结

该篇博文介绍了微信从 8.28 起进行了微信获取手机号的变更,介绍了在微信官方的组件 API 调用示例以及在后台的付费管理收费方式概述,最重要是在源码章节中,采用了 Github 微信组件库的封装代码进行微信授权、新版|旧版微信手机号获取 API 调用,对微信接口返回的一些核心参数进行了详细的阐述以及在业务系统中需要注意的地方,避免在工作中偷一时的懒而影响后续的系统整改(使用微信 sessionKey 作为小程序用户缓存唯一标识)

🌟🌟🌟愿你我都能够在寒冬中相互取暖,互相成长,只有不断积累、沉淀自己,后面有机会自然能破冰而行!

博文放在 微信体系 专栏里,欢迎订阅,会持续更新!

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

推荐专栏:Spring、MySQL,订阅一波不再迷路

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1151493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL注入——二次注入漏洞

文章目录 SQL注入——二次注入漏洞1. 二次注入原理2. 二次注入需要具备的两个条件3. 二次注入实例4. 总结 SQL注入——二次注入漏洞 1. 二次注入原理 在第一次插入恶意数据的时候&#xff0c;只是对其中的特殊字符进行了转义&#xff0c;在写入数据库的时候还是原来的字符&am…

9.多线程之定时器与线程池

定时器与线程池 文章目录 定时器与线程池1. 定时器1.1 定时器的工作原理1.2 定时器的使用2.3 实现定时器 2. 线程池2.1 线程池存的优点2.2 线程池的使用2.3 线程池的原理2.3.1 工厂模式2.3.2 ThreadPoolExecutor类 2.4 实现线程池 1. 定时器 定时器也是软件开发中的一个重要组件…

【GEE】Google Earth Engine(GEE)注册详细教程无需教育邮箱

这个专栏真的是纠结了很久&#xff0c;不知道到底要不要分享自己在学习GEE的时候的一些经验和代码。因为本人在日常中使用Python和ENVI多点&#xff0c;虽然GEE也会用但不至于频繁使用&#xff0c;同时针对GEE其实官网给出了很多接口的使用方法&#xff0c;国内外也有很多人分享…

编译正点原子LINUXB报错make: arm-linux-gnueabihf-gcc:命令未找到

编译正点原子LINUXB报错make: arm-linux-gnueabihf-gcc&#xff1a;命令未找到 1.报错内容2.解决办法3./bin/sh: 1: lzop: not found4.编译成功 1.报错内容 make: arm-linux-gnueabihf-gcc&#xff1a;命令未找到CHK include/config/kernel.releaseCHK include/genera…

全面提升企业管理效率,助力企业持续增长——三叠云进销存解决方案

企业在生产经营过程中&#xff0c;高效的进销存管理是企业成功的关键因素之一。它不仅能够优化企业的资金流动&#xff0c;避免库存积压和断货现象&#xff0c;提高客户满意度&#xff0c;而且可以优化供应链&#xff0c;减少运营成本&#xff0c;提高生产和物流效率。三叠云正…

C语言 数据的存储2

如图所示代码&#xff1a; 代码运行结果为&#xff1a; 这是什么原因呢&#xff1f; 解析: 因为unsigned int是无符号整形&#xff0c;而我们的for循环的条件是 所以我们会一直循环下去&#xff0c;至于我们的结果为什么会是 一个unsigned int类型是4个字节&#xff0c;38位&am…

论文范文:论基于架构的软件设计方法及应用

注意:范文只适用于帮助大家打开写作思路,并不能作为素材直接用于平时练习、考试中。考试中直接使用范文的素材,会有被认定为雷同卷的风险。 摘要: 2022年4月,本人所在单位计划研发生态集装箱管理控制平台项目。该平台主要用于与现有公司生态集装箱产品做对接,达到远程控制…

【AI视野·今日Robot 机器人论文速览 第六十期】Mon, 23 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Mon, 23 Oct 2023 Totally 26 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers A Review of Prospects and Opportunities in Disassembly with Human-Robot Collaboration Authors Meng Lun Lee, Xiao Lian…

vscode开启emmet语法

需要在setting.json中添加配置 首先进入设置&#xff0c;然后点击右上角 Vue项目添加如下配置 "emmet.syntaxProfiles": { "vue-html": "html", "vue": "html" },React项目添加如下配置 "emmet.includeLanguages&quo…

Google搜索中,搜索关键词的技巧

最近在b站看到一个关于搜索的视频&#xff0c;感觉比较有用&#xff0c;先mark下来 1、巧用限定关键词符号""&#xff0c;也就是用英文的双引号&#xff0c;去搜索包含搜索词及这个搜索词字序的搜索结果。 如搜索 "菊花茶"&#xff0c;这个有用的点在于…

OpenCV官方教程中文版 —— Hough 圆环变换

OpenCV官方教程中文版 —— Hough 圆环变换 前言Hough 圆环变换 前言 目标 • 学习使用霍夫变换在图像中找圆形&#xff08;环&#xff09; • 学习函数&#xff1a;cv2.HoughCircles() Hough 圆环变换 opencv_logo.png&#xff1a; # -*- coding: utf-8 -*- import cv2 …

生态系统服务(InVEST模型)的人类活动、重大工程生态成效评估、论文写作等具体应用

以InVEST模型结合实际项目进行由浅入深的实战技术培训&#xff0c;Ai尚研修针对11期InVEST模型实践技术会议参会学者的特点及需求进行分析&#xff0c;融合课程体系&#xff0c;对接工作实际项目及论文写作&#xff0c;解决参会者关注的重点及实际项目过程问题&#xff0c;课程…

C++新经典 | 记录在最后的高阶知识点

目录 一、函数调用运算符与function类模板 1.函数调用运算符 &#xff08;1&#xff09;函数类型 &#xff08;2&#xff09;可调用对象 2.function类模板 二、万能引用类型 1.万能引用 2.万能引用资格的剥夺与辨认 &#xff08;1&#xff09;const修饰词 &#xff0…

人工智能基础_机器学习011_梯度下降概念_梯度下降步骤_函数与导函数求解最优解---人工智能工作笔记0051

然后我们来看一下梯度下降,这里先看一个叫 无约束最优化问题,,值得是从一个问题的所有可能的备选方案中选最优的方案, 我们的知道,我们的正态分布这里,正规的一个正态分布,还有我们的正规方程,他的这个x,是正规的,比如上面画的这个曲线,他的这个x,就是大于0的对吧,而现实生活…

Java反射调用ashx

这篇文章卡了大概一周&#xff0c;一个是没时间&#xff0c;只能带娃加锻炼间隙挤点时间&#xff0c;一个是碰到了问题卡住了。本篇实现反射调用ashx实现类的基础结构。 首先申明ashx的接口&#xff0c;所有的ashx实现类继承实现该接口的基类 package appcode; import java.i…

dbeaver查看表,解决证书报错current license is non-compliant for [jdbc]

http://localhost:9200/_license { “license” : { “status” : “active”, “uid” : “b91ae0e0-b04d-4e20-8730-cf0bca7b2035”, “type” : “basic”, “issue_date” : “2023-02-22T14:33:27.648Z”, “issue_date_in_millis” : 1677076407648, “max_nodes” : 10…

Leetcode 43. 字符串相乘 中等

题目 - 点击直达 1. 43. 字符串相乘 中等1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 思路一 做加法1. 思路分析2. 时间复杂度3. 代码实现 3. 思路二 做乘法1. 思路分析2. 时间复杂度3. 代码实现 1. 43. 字符串相乘 中等 1. 题目详情 给定两个以字符串形式表示的非负整…

react中的useState和useImmer的用法

文章目录 一、useState1. 更新基本类型数据2. 更新对象3. 更新嵌套对象4. 更新数组5.更新数组对象 二、Immer1. 什么是Immer2. 使用use-immer更新嵌套对象3. 使用useImmer更新数组内部的对象 一、useState react中文官网教程 1. 更新基本类型数据 在函数式组件中&#xff0c…

【多线程相关其二】进程与线程

进程vs线程 进程&#xff08;process&#xff09;指的是正在运行的程序的实例&#xff0c;即an instance of a computer that is being executed。用拆字法理解就是&#xff1a;进行中的程序。程序是一个没有生命的实体&#xff0c;只有处理器执行它的时候才能成为一个活动的实…

macOS 创建Flutter项目

参考在 macOS 上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 这个文档&#xff0c;配置好flutter的环境 编辑器可以选择vscode或者IDEA。 我这里以IDEA为例 打开 IDE 并选中 New Flutter Project。 选择 Flutter&#xff0c;验证 F…