微信相关接口封装,示例代码所用框架 ThinkPHP6 配置公众号
使用微信公众号实现微信扫码登陆的逻辑 1. 微信端实现扫码事件操作通过微信发送给开发者服务器 2. 开发者服务器接收并处理二维码中的参数,并存储到服务器中 3. 开发者浏览器端轮询确认用户是否登陆成功
Wx.php
<?php
namespace app\index\logic;
use app\index\model\TabUser;
use think\Exception;
use think\facade\Log;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelLow;
class Wx
{
// 存储当前对象
private static $instance = null;
// 禁止被实例化
private function __construct()
{ }
// 禁止 clone
private function __clone()
{ }
// 实例化自己并保存到 $instance 中,已实例化则直接调用
public static function getInstance()
{if(empty(self::$instance)){self::$instance = new self();
}
return self::$instance;
}
public $appid='wxcdde******b20';
public $appsecret='2da42c6f*****1e2ad061d57f7712';
public $token = 'n4xmyq3z0*****rrhjwe11ow0u15uu1';
public $EncodingAESKey = 'cbyrq3Cz4N1mdWqQ7bOvYLP58zKSNUytX8yc4TjWiOU';
private function auth(){
$token=$this->token;
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if(trim($tmpStr) == trim($signature)){if(isset($_GET['echostr'])){echo $_GET['echostr'];
exit;
}else{return false;}
}else{return false;}
}
//token
public function token(){$this->auth();
$postData = file_get_contents('php://input');
libxml_disable_entity_loader(true);
$data = $this->xmlToArray($postData);
Log::info($data);
if($data['MsgType']=='event'){ // 事件处理
if($data['Event']=='unsubscribe'){// 取消关注的事件
$this->unsubscribe($data);
}else if($data['Event']=='subscribe'){// 关注的事件
$this->subscribe($data);
}else if($data['Event']=='SCAN'){// 扫描带参二维码事件
$this->scan($data);
}
}
}
//xml 转数组
private function xmlToArray($xml)
{if (file_exists($xml)) {libxml_disable_entity_loader(false);
$xml_string = simplexml_load_file($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
} else {libxml_disable_entity_loader(true);
$xml_string = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
}
$result = json_decode(json_encode($xml_string), true);
return $result;
}
/**
* 获取 access_token,用于获取用户信息
* @param $code 用户扫码登录成功后,回调带的 code
* @return mixed
*/
private function get_access_token(){
$cache_key = 'wx_access_token_'.$this->appid;
if(!cache($cache_key)){
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->appid."&secret=".$this->appsecret;
$data = json_decode(curl_request($url),true);
if(isset($data['access_token'])){cache($cache_key, $data['access_token'],$data['expires_in']-600);
}else{Log::error($url. ' 请求失败 ');
throw new Exception(' 微信接口请求失败 ');
}
}
return cache($cache_key);
}
/**
* 获取用户信息
* @param $access_token string access_token
* @param $openid string 微信用户标识
* @return mixed
*/
private function get_user_info($access_token, $openid){
$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
return json_decode(curl_request($url),true);
}
/**
* 写入用户信息到数据表
* @param $openid
* @param $EventKey
*/
private function register($openid, $EventKey)
{$model = new TabUser();
$data['account'] = Login::create_account();
$data['nickname'] = $data['account'];
$data['password'] = $data['account'];
$data['openid'] = $openid;
$result = $model->insert($data);
cache('login_'.$EventKey,json_encode($result),'50');
}
/**
* 扫描带参二维码事件
*/
private function scan($data)
{$access_token= $this->get_access_token();
$user_['access_token']=$access_token;
$user_['openid']= $data['FromUserName'];
$EventKey = $data['EventKey'];
if(isset($user_['openid'])){
// 说明获取用户信息获取成功了
$info = cache('login_'.$EventKey);
if(empty($info)){$users = TabUser::where(['openid'=>$user_['openid']])->find();
if($users){cache('login_'.$EventKey,json_encode($users),'50');
}else{
// 注册
$this->register($data['FromUserName'], $EventKey);
}
$msg = ' 登陆成功!';
$textTpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><Content><![CDATA[%s]]></Content></xml>";
$resultStrq = sprintf($textTpl,$data['FromUserName'],$data['ToUserName'], time(), 'text', $msg);
echo $resultStrq;
exit;
}
}
}
/**
* 关注订阅
*/
private function subscribe($data)
{$EventKey = explode("_", $data['EventKey'])[1];
$access_token= $this->get_access_token();
$user_['access_token']=$access_token;
$user_['openid']=$data['FromUserName'];
if(isset($user_['openid'])){
// 说明获取用户信息获取成功了
$info=cache('login_'.$EventKey);
if(empty($info)){$users = TabUser::where(['openid'=>$user_['openid']])->find();
if($users){//Db::table("tab_wx_log")->insert(array('session_str'=>444,'content'=>444));
cache('login_'.$EventKey,json_encode($users),'50');
}else{
// 注册
$this->register($data['FromUserName'], $EventKey);
//Db::table("tab_wx_log")->where(['session_str'=>666])->update(array('content'=>$data['FromUserName']));
}
$msg = ' 登陆成功!';
$textTpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><Content><![CDATA[%s]]></Content></xml>";
$resultStrq = sprintf($textTpl,$data['FromUserName'],$data['ToUserName'], time(), 'text', $msg);
echo $resultStrq;
exit;
}
}
}
/**
* 取消订阅
*/
private function unsubscribe($data)
{echo ' 取消关注 ';exit;}
/**
* 获取微信场景二维码
* @param $sceneValue 场景值
* @param int $type 1:临时二维码 2:永久二维码
* @return string
*/
public function getWeChatUrl($session_str,$code){cache('login_'.$session_str,true,50); // 用户客户端标识
cache('code_'.$session_str,$code,50); // 邀请码
$type=1;
$access_token = $this->get_access_token();
$url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token='.$access_token;
$actionName = 'QR_STR_SCENE';
if($type==2){$actionName = 'QR_STR_SCEN';}
$data = json_encode([
'expire_seconds'=>604800,
'action_name'=>$actionName,
'action_info'=>[
'scene'=>[
'scene_id'=>$session_str,
'scene_str'=>$session_str
]
]
]);
$res = curl_request($url, true ,$data);
$res = json_decode($res,true);
if(isset($res['errcode']) && $res['errcode']){throw new Exception(' 二维码接口请求失败 ');
}
return $res['url'];
}
/**
* 功能:生成二维码 base64 图片
* @param string $qrData 手机扫描后要跳转的网址
* @param string $qrLevel 默认纠错比例 分为 L、M、Q、H 四个等级,H 代表最高纠错能力
* @param string $qrSize 二维码图大小,1-10 可选,数字越大图片尺寸越大
* @param string $savePath 图片存储路径
* @param string $savePrefix 图片名称前缀
* @return mixed
*/
public function createQRcode($qrData = '', $qrSize = 200)
{$writer = new PngWriter();
$qrCode = new QrCode($qrData);
$qrCode->setEncoding(new Encoding('UTF-8'));
$qrCode->setErrorCorrectionLevel(new ErrorCorrectionLevelLow());
$qrCode->setSize($qrSize);
$qrCode->setMargin(10);
$result = $writer->write($qrCode);
return $result->getDataUri();}
/**
* 生成唯一客户端 id 标识
* @return string
*/
public function create_session_str()
{
$str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$len = strlen($str)-1;
$randstr = '';
for ($i=0;$i<6;$i++) {$num=mt_rand(0,$len);
$randstr .= $str[$num];
}
$session_str = $randstr.uniqid();
return $session_str;
}
}
控制器
class login
{
/**
* 微信 token 验证
* 微信服务端与开发者客户端交互接口
*/
public function token()
{Wx::getInstance()->token();}
/** * 携带客户端表示,显示二维码 */
public function qrcode($session_str, $code='') {$url = Wx::getInstance()->getWeChatUrl($session_str,$code);
$base64_img = Wx::getInstance()->createQRcode($url);
echo $base64_img;
}
/** * 轮询请求是否扫码登陆成功 */
public function check_login($session_str, $code='') {if(cache('login_'.$session_str)){return ture;} else{return false;}
}
/** * 生成 session_str 客户端唯一标识 * 在生成微信登陆二维码时携带 session_str 参数 */
public function index($session_str, $code='') {$session_str = Wx::getInstance()->create_session_str();
echo $session_str;
}
}
···
正文完
有偿技术支持加微信