2026-06-21 18:36:19

微信小程序 接口调用讲解 (AccessToken、小程序码登录)

前言当前对于网站项目的开发,针对于客户使用的 小程序是最为主要的

在此整理几个使用频率高的接口

方便开发人员的后期参考,以及对功能的快速实现 重要分享接口 梳理 下面,整理出实际业务中,使用频率较高的接口,做下分享

1 登录信息获取 ♘链接 - 开放文档 ->>> 小程序登录

【场景描述】

当用户在我们开发的小程序中,点击授权登录时

我们可以通过微信官方提供的登录能力,方便地获取用户 身份标识,

从而将微信用户与我们的产品数据进行绑定,快速建立起小程序内的用户体系 之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份

登录流程时序如下: 简而言之,我们要获取微信用户的唯一标识 OpenID ,关联自己的业务

接口描述 【请求地址】:【GET】 https://api.weixin.qq.com/sns/jscode2session 【请求参数 】参数名

必选

类型

说明

appid

string

小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页面获得

secret

string

小程序唯一凭证密钥,即 AppSecret,获取方式同 appid

js_code

string

登录时获取的 code (小程序端通过 wx.login 接口获得临时登录凭证 code)

grant_type

string

授权类型,此处只需填写 authorization_code

【返回参数】参数名

类型

说明

openid

string

用户唯一标识

session_key

string

会话密钥 session_key 是对用户数据进行 加密签名 的密钥

unionid

string

用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回

errcode

string

错误码: -1、0、40029、 45011、 40226 (具体说明,请阅读 接口文档)

errmsg

string

错误信息

示例代码【PHP 示例代码】

(😦 tip: 公共方法 do_curl_get_request() 可见附录)代码语言:javascript复制 $url = 'https://api.weixin.qq.com/sns/jscode2session';

$param = [

'appid' => 'xxxxxxx',

'secret' => 'xxxxxxxxxxxxxxxx',

'js_code' => 'CODE',// 小程序端通过 wx.login 接口获得临时登录凭证 code

'grant_type' => 'authorization_code',

];

$res = do_curl_get_request($url,$param);[提示]小程序登录成功后,将登录信息(openid、session_key)保存下来

即,保存登录令牌Token,方便用户登录状态的维持

在接下来的获取接口,有令牌就可以 访问,没有的话就不能访问对于为什么要换取 Token,如何使用 Token,可以参考下面的两篇文章: ♘ 登录与令牌 小程序用户怎么拿到 token 的? ♘ 微信小程序登录换取 token

如果,需要获取微信用户的 昵称,地址、微信头像等信息

可以参考接口 —— 开放数据校验与解密 进行有效信息的获取 接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和 unionId), 需要对接口返回的加密数据(encryptedData) 进行对称解密

最终解密获得的 json 数据如下:代码语言:javascript复制{

"openId": "OPENID",

"nickName": "NICKNAME",

"gender": GENDER,

"city": "CITY",

"province": "PROVINCE",

"country": "COUNTRY",

"avatarUrl": "AVATARURL",

"unionId": "UNIONID",

"watermark":

{

"appid":"APPID",

"timestamp":TIMESTAMP

}

} 一般用于,对新注册微信用户的绑定记录,方便我们在自己网站业务中的用户识别操作

2 接口调用凭证 AccessToken ♘链接 - 开放文档 ->>> auth.getAccessToken

【场景描述】

首先,要明确一点

此处提到的access_token ,是 作为 小程序 全局唯一 后台接口调用凭据

而对于服务端的接口来说

绝大部分的服务,都需要使用 access_token,开发者需要进行妥善保存♦ 接口描述 【请求地址】:【GET】 https://api.weixin.qq.com/cgi-bin/token 【请求参数 】参数名

必选

类型

说明

grant_type

string

填写 "client_credential"

appid

string

小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页面获得

secret

string

小程序唯一凭证密钥,即 AppSecret,获取方式同 appid

正常时返回: {"access_token":"ACCESS_TOKEN","expires_in":7200}

错误时返回:{"errcode":40013,"errmsg":"invalid appid"}

♦ 示例代码【PHP 示例代码】

(😦 tip: 公共方法 do_curl_get_request() 可见附录)代码语言:javascript复制 $url = 'https://api.weixin.qq.com/cgi-bin/token';

$param = [

'grant_type' => 'client_credential',

'appid' => 'wxexxxxxxxx',

'secret' => 'f6eebxxxxxxxxxxxxxxxxxxxxx'

];

//返回数据,自行提取保存

$res = do_curl_get_request($url,$param);♦ [提示] 如果没有 redis,也可存储在 mysql 数据表,服务器session、甚至 file 文件中,只要保证读取时间有效即可

3 小程序码 登录 ♘链接 - 开放文档 ->>> awxacode.getUnlimited

【场景描述】

以实际开发场景为例:

为了便于商家登录PC端,将原来的 短信验证码登录 替换为 微信小程序码 扫码登录

商家扫码后,微信端会跳入小程序页面,

同时,PC端会自动进入网站,简化登录流程,提高用户体验 整体流程演示图:♦ 接口描述 请求地址:

【POST】 https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN 【请求参数 】参数名

必选

类型

说明

access_token

string

接口调用凭证

scene

string

场景信息,最大32个可见字符,只支持数字,大小写英文以及部分特殊字符 以我的代码实现为例,设定的字符串为: pc_code=$pc_code

page

string

页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面

注:对于参数 scene,其中的 pc_code 值,可以在 PC 端请求小程序码时,随机生成,可用时间戳+随机数,后续的逻辑中,会以此 pc_code 判断哪个码扫码登录成功

【开发思路】代码语言:javascript复制1. 用户在 PC 端请求显示 小程序码时,需要一个传一个参数 pc_code (可用时间戳+随机数)

2. 后台,curl 调用微信服务接口,获取小程序码,返回到 PC 端显示

3. 后台将这个 pc_code,进行 redis 存储,状态 status 设定为 未登录状态

$value = ['status'=>0,'create_time' => time()];

$redis->hSetNx($cache_key_pc_scan_mini_code,$pc_code)

4. 如果,小程序检测到登录,

要更新 redis, 状态 status 设定为 已登录状态

5. PC端,设定一个轮询 js (条件允许的话,可以考虑使用 websocket)

每秒查看 status 是否失效、已登录

如果失效(5分钟),要重新获取新的 小程序码,或引导用户刷新页面

如果登录成功,根据返回的 用户Token,进行登录后业务处理

6. 设计一个计划任务,处理已过时的 小程序码,做好交互 示例代码生成 小程序码代码语言:javascript复制 /**

* 获取不受限制的小程序二维码

* @param $page string 页面路径

* @param $scene string 携带参数

* @param $width int 宽度

* @param $color array 颜色

* @param $isHyaline boolean 是否透明底色

* @return string

*

* @throws Exception

*/

public function unlimitedAcode(string $scene, string $page='', int $width=50, array $color=[], bool $isHyaline=false)

{

$url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit';

$query = [

'access_token' => $this->accessToken()

];

$data = [

'scene' => $scene,

'width' => $width,

'auto_color' => $color ? false : true,

'is_hyaline' => $isHyaline

];

if ($page) {

$data['page'] = $page;

}

if (!$data['auto_color']) {

$data['line_color'] = [

'r' => $color[0],

'g' => $color[1],

'b' => $color[2]

];

}

$client = new Client([

'query' => $query,

'body' => json_encode($data)

]);

$res = $client->post($url);

return $res->getBody()->getContents();

}更新 商家PC端 小程序码状态信息代码语言:javascript复制 /**

* 更新 商家PC端 小程序码状态信息

* @param int $opTag 1:获取小程序码;2:检测小程序码,扫码状态;3:商家小程序端,登录后的缓存更新

* @param string $pc_code PC端,标识码

* @param string $scan_open_id $opTag=3 时,需要传参

* @return array

*/

public static function opCacheKeyScanMiniCode($opTag = 1,$pc_code = '',$scan_open_id = ''){

$cache_key_pc_scan_mini_code = config('mz.pc_scan_mini_code');

$redis = redis();

if($opTag === 1){

//获取小程序码后,进行 redis 存储

$value = ['status'=>0,'create_time' => time()];

$redis->hSetNx($cache_key_pc_scan_mini_code,$pc_code,json_encode($value,JSON_UNESCAPED_UNICODE));

}elseif ($opTag === 2){

//此时为,获取小程序码 状态信息

$scanVal = $redis->hget($cache_key_pc_scan_mini_code,$pc_code);

$scan_open_id = '';

if ($scanVal){

$arr_scanVal = json_decode($scanVal,true);

$scan_status =$arr_scanVal['status']??0;

if ($scan_status == 0){

//判断是否已过期

$create_time =$arr_scanVal['create_time']??0;

if ((time()-$create_time)> 300){

//暂定 5分钟后 失效 (小程序码已过期)

$scan_status = 2;

//TODO 可设计一个计划任务,剔除已超时的键

}

}else{

$scan_open_id =$arr_scanVal['open_id']??'';

}

}else{

//为了前端显示的判断,也设定为 失效

$scan_status = 2;

}

return [$scan_status,$scan_open_id];

}elseif ($opTag === 3){

//此时,小程序端,登录成功后,更新用户信息

$scanVal = $redis->hget($cache_key_pc_scan_mini_code,$pc_code);

if ($scanVal){

$arr_scanVal = json_decode($scanVal,true);

$arr_scanVal['status'] = 1;

$arr_scanVal['open_id'] = $scan_open_id;

$redis->hSet($cache_key_pc_scan_mini_code,$pc_code,json_encode($arr_scanVal,JSON_UNESCAPED_UNICODE));

}

}

}

/**

* //TODO 考虑,去除已登录、超时的键

* 去除 超时的键

*/

public static function updateCacheKeyScanMiniCode(){

$cache_key_pc_scan_mini_code = config('mz.pc_scan_mini_code');

$redis = redis();

$list = $redis->hGetAll($cache_key_pc_scan_mini_code);

foreach ($list as $key => $val){

$arr_cache_val = json_decode($val,true)??[];

$create_time = $arr_cache_val['create_time']??0;

if ((time() - $create_time) > 300){

//此为 设定超时的键 5分钟

$redis->hDel($cache_key_pc_scan_mini_code,$key);

}

}

return [true,'PC端登录小程序码,更新成功'];

}接口返回代码语言:javascript复制{

"code": 200,

"msg": "小程序码获取成功!",

"data": {

"mini_code": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD..."

}

}♦ [提示]① 小程序码登录优势代码语言:javascript复制1. 使用小程序码登录,用户真正登录行为发生在小程序上,同步给网页的是登录态,

相比于微信二维码登录同步给网页临时 code,

然后在重定向到业务登录后台换取登录态方式,

小程序码方式少了一次请求,带来更佳用户体验

2. 整体登录流程,UI更可控,也便于登录问题定位② 【经验建议】 对于前面提到的 pc_code 值的设定建议代码语言:javascript复制 对于 pc_code 值,如果使用了 “时间戳+随机数”:

实际上,很可能会被恶意人员暴力破解,简单的就猜到了我们的实现逻辑,从而截取数据,分析出我们网站的登录数据

此时,可以考虑:

对这里的 pc_code 值做加密操作,

—— 设计加密逻辑,每隔一段时间加密参数变动即可,避免恶意破解③. 【经验建议】 对于页面使用 js 轮询获取 小程序码扫码状态的建议代码语言:javascript复制 相对来说,设计为简单的 js 轮询方式

无疑是对 资源请求的一种浪费,虽然接口中的代码逻辑耗时可忽略

但,难免遇到恶意份子的 暴力请求情况

首先,一种最简单的优化方式:

—— 轮询时间缩短,比如一分钟,如此一来直接在用户行为上,降低了无效请求

其次,可以考虑比较常用的 websocket 长链接方式:

—— 将原来的被动请求,变为主动触发,减少资源的请求浪费 (听起来就高大上一些) 参考文章:

♘ 通过微信小程序实现扫码登录

♘【网页版】使用小程序码登录

♘ 通过扫小程序码实现网站登录功能

附录公共方法代码语言:javascript复制/**

* CURL-get请求

* @param string $url 请求的url

* @param array $param 请求的参数

* @param string $output 输出格式

* @param int $timeout 超时时间

* @return mixed 数组形式

*/

function do_curl_get_request($url = '', $param = [],$output = 'json', $timeout = 10)

{

$ch = curl_init();

if (is_array($param)) {

$url = $url . '?' . http_build_query($param);

}

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); // 允许 cURL 函数执行的最长秒数

$data = curl_exec($ch);

curl_close($ch);

if ($output == 'json') {

$json = json_decode($data , true);

return $json ?? $data ;

} else {

return $data ;

}

}

/**

* CURL-post请求

* @param string $url 请求的url地址

* @param array $param 请求的参数

* @param array $header

* @param string $output 输出格式

* @param int $timeout 超时时间

* @return mixed

*/

function do_curl_post_request($url = '', $param = [], $header = [], $output = 'json',$timeout = 10)

{

$ch = curl_init();

if (is_array($param)) {

$urlparam = http_build_query($param);

} else if (is_string($param)) { //json字符串

$urlparam = $param;

}

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); //设置超时时间

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回原生的(Raw)输出

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

curl_setopt($ch, CURLOPT_POST, 1); //POST

curl_setopt($ch, CURLOPT_POSTFIELDS, $urlparam); //post数据

if ($header) {

curl_setopt($ch, CURLOPT_HTTPHEADER, $header);

}

$data = curl_exec($ch);

curl_close($ch);

if ($output == 'json') {

$json = json_decode($data , true);

return $json ?? $data ;

} else {

return $data ;

}

}

深入解析可汗学院三个平台的使用技巧与误区,提升孩子学习效率!
堕落精华