扫小程序码登陆网站方案的 .web服务器部分代码和逻辑.

 

总体就是四步骤.

 

1,生成一个二维码.

2,等待扫码登陆,微信小程序返回结果.

3,解密微信小程序结果,获取并记录用户信息,

4,web用户登陆.

 

 

生成带参数二维码

 

我用的是overtrue/wechat包

 

init

$wxinfo['app_id'] = 'appid';
$wxinfo['secret'] ='secret';

$this->miniapp =Factory::miniProgram($wxinfo);

 

二维码

 

echo $this->miniapp->app_code->getUnlimit($request_str);
exit;

直接用echo输出,因为返回的图片HTTP流,而不是一个图片链接.

输出后结束函数.

 

$request_str 就是你要生成的参数.这个是写入数据库的.

 

微信小程序扫码后会得到这个值.

 

登陆轮询

 

这个无非就是判断$request_str有没有被使用,自己加一个标记比如isUse字段. 当微信小程序扫码后,更新这个字段.

轮询的时候不过就是循环判断这个值是否更新了.是一个比较简单的操作.

 

 

小程序对接

 

参数

 

我有个对外的api接口,专门给小程序登陆提交过来的.

 

public function pushCode(String $code,String $scene ,String $iv ,String $encryptedData){
//....
}

 

需要接收的参数就是上面4个.

$scene就是之前$request_str

 

判断

 

在解码之前,

得判断下参数是否存在.

$scene是否存在,或者是否过期.

 

获取session_key

session_key就是解密用户信息用的密钥.

需要调用微信小程序API获取.

 

 

我自己将code用个数据库缓存了起来,如果不存起来,短时间,连续扫码会解密失败..

如果code没有记录,那么调用

$this->miniapp->auth->session($code);

获取解密用的session_key,

如果有记录那么直接数据库拿.

 

//看看code缓存
$minicodeinfo = Minicode::where(['code'=>$code])->find();

if (empty($minicodeinfo)){

	try {
		$res = $this->miniapp->auth->session($code);
		$session_key = $res['session_key'] ;
	} catch (Exception $e){
		throw new Exception('小程序code过期,考虑清小程序缓存.');
	}

}else{
	$session_key =  $minicodeinfo -> session_key;
}

 

解密用户信息

if (!empty($session_key)){

	try {
		$rrs = @$this->miniapp->encryptor->decryptData($session_key, $iv, $encryptedData);
	} catch (Exception $e) {
		throw new Exception('小程序异常,考虑清小程序缓存.');
	}

	//...........

else{
	//return $this->error(-191,'解密错误,考虑清空小程序缓存.','微信错误信息: ' . $res['errmsg']);
}       

 

直接调用接口即可.

$rrs就是解密后的用户信息

 

内容就是

 

{
	"openId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
	"nickName": "Y.A.K.E",
	"gender": 1,
	"language": "zh_CN",
	"city": "Xinyu",
	"province": "Jiangxi",
	"country": "China",
	"avatarUrl": "https://wx.qlogo.cn/mmopen/vi_32/WWCC67raM9t3A05kuyjmR3tXlLor4DQkFwmSBY3icN0YYjPtZudf2mBsVv1C5CGkaAibjKBDBicOysRP1nFqtgjrA/132",
	"unionId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
	"watermark": {
	  "timestamp": 1543412981,
	  "appid": "wx8a18e3c3091991ef"
 }

 

openId 就是用户 对当前小程序唯一ID

unionId 就是用户对  你微信开发平台账号(主体) 唯一ID.

unionId 必须要在微信小程序绑定开发者平台的情况下才能获取到.前面说过,这是一个免费的操作.

 

 

 

 

新增或者更新用户信息

 

$allow_field = array('nickName','openId','gender','language','city','province','country','avatarUrl');
User::update($vrrs, ['unionId' => $rrs['unionId']],$allow_field);

我的主键是id,和unionId.

更新或者新建都是最基本的数据库操作.

 

判断登陆

 

也就是给数据写入一个登陆标记.

通过$request_str判断.

写入一个isUse标记.同时将用户ID写入二维码记录表.

那么前台轮询就会判断已经登陆.

 

自动登陆

 

自动登陆是轮询的时候同时干的事.

 

$qr_info = Qr::where('request_str',$request_str)->find();

然后判断isUse字段是否更新了.

更新了同时应该还有userId .

 

拿到userId后,然后开始写出cookie到浏览器就完成了登陆了.

 

 

补充和注意事项

 

二维码

 

小程序调用接口生成临时二维码有调用次数限制.

微信小程序规定每分钟调用生成临时二维码接口不能超过5000次.

超过限制,接口调用失败.直到下一分钟恢复.

 

算的. 也就是说,相同参数,一次请求就算一次,多次请求,就算多次.

如果有人恶意刷新我二维码页面,每分钟刷新5000次.那么我博客二维码就会因为接口调用次数超过限制.就会用不了.

 

如果接口调用次数不想浪费,那么还可以缓存二维码图片到服务器.

 

 

 

我没去缓存,换了一个比较懒的方案.

生成的二维码有效期建议拉长一些.

我博客是30分钟.也就是生成二维码之后,会在30分钟轮询是否登陆.超过30分钟才算超时.

 

 

 

多小程序联合

 

也就是unionid概念.

 

 

我准备了两个个备用小程序.

 

小程序内容随便弄的.没啥功能.

完全是备胎.随时准备切换的.

做好了博客授权登陆.

暂时没有启用.

 

其他一样

唯一不同点. 就是每个用户,不同小程序openid不同.

绑定同一个开发者平台账号,unionid是相同的.

听起来有点不太明白.

 

  小程序A 小程序B
用户 openid unionid openid unionid
张三 O1 U1 OX1 U1
李四 O2 U2 OX2 U2
王五 O3 U3 OX3 U3

 

 

张三,在不同微信小程序,微信公众号,的openid都不相同.

张三,在不同微信小程序,微信公众号的unionid都相同.

 

unionid相同,是有主体的概念.

一个开发者(微信开放平台)账号是一个主体 .

小程序A和小程序B必须绑定在同一个开发者(微信开放平台)账号.

才会使得张三在小程序A和B中的unionid值相同.

 

如果小程序A解绑了原来的开发者(微信开放平台)账号

而绑定到了其他的开发者(微信开放平台)账号.

那么张三的unionid也会变更.