第一步,经过ComponentTicket获取component_access_tokenjson
直接上代码:小程序
由于ComponentAccessToken天天的获取次数是有限制,博主也没有测试过具体多少次。因此根据微信的提示作了个判断当ComponentAccessToken的校验时间戳小于当前时间戳180秒后,从新获取一下ComponentAccessToken,下面是逻辑:api
/**
* 微信获取ComponentAccessToken
* @access public
*
*/
public function getComponentAccessToken()
{
$returnArray = array();
//这里'type'是不一样类型的AccessToken,我这边有小程序、公众号、第三方平台的,因此用'type'区分开来,2表明第三方平台
//获取最新的第三方平台的AccessToken
$wxAccessToken = self::where(array('type'=>2))->order(array('id'=>'desc'))->limit(1)->select();
if($wxAccessToken){
$wxAccessToken = $wxAccessToken[0]->toArray();
//判断是否过时
if((time() - $wxAccessToken['check_time']) < -180){
$returnArray = array(
'code' => 1,
'info' => array(
'access_token' => $wxAccessToken['access_token'],
'end_time' => $wxAccessToken['check_time']
)
);
}else{
//过时了从新获取
$returnArray = self::setComponentAccessToken();
}
}else{
//没有AccessToken从新获取
$returnArray = self::setComponentAccessToken();
}
return $returnArray;
}缓存
这是从新获取ComponentAccessToken的核心代码微信
/**
* 经过component_verify_ticket获取component_access_token并保存
* @access public
*
*/
public function setComponentAccessToken()
{
$returnArray = array();
//初始化ComponentTicket模型(保存微信每10分钟传过来的ComponentTicket)
$wxComponentTicketModel = new \app\diuber\model\WxComponentTicket();
//获取数据库中最新的一个ComponentTicket
$componentTicketRow = $wxComponentTicketModel->order(array('id'=>'desc'))->limit(1)->select();
if($componentTicketRow){
$componentTicket = $componentTicketRow[0]->toArray();
$row = json_encode(array(
'component_appid' => $this->appid,
'component_appsecret' => $this->appsecret,
'component_verify_ticket' => $componentTicket['component_verify_ticket']
));
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $row);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output, true);
if(!empty($output['component_access_token']) && !empty($output['expires_in'])){
$checkTime= time() + $output['expires_in'];
$data = array(
'access_token' => $output['component_access_token'], //AccessToken
'type' => 2,//类型(1.小程序 2.第三方平台 3.公众号)
'create_time' => date('Y-m-d H:i:s'),
'check_time' => $checkTime //校验时间戳
);
//建立AccessToken记录
$wx = self::create($data);
if(!$wx){
$returnArray = array(
'code' => 0,
'info' => '后台保存失败!'
);
}else{
$returnArray = array(
'code' => 1,
'info' => array(
'access_token' => $data['access_token'],
'end_time' => $data['check_time']
)
);
}
}else{
$returnArray = array(
'code' => 0,
'info' => '微信端获取失败!'
);
}
}
return $returnArray;
}app
第二步、经过component_access_token获取预受权码pre_auth_code微信公众平台
代码以下:这个预受权码是为了获取正式受权码准备的,使用一次就会失效,因此没有去作缓存
/**
* 经过component_access_token获取pre_auth_code
* @access public
*
*/
public function getPreAuthCode()
{
$returnArray = array();
//获取component_access_token
$componentAccessTokenRow = self::getComponentAccessToken();
if($componentAccessTokenRow['code'] == 1){
$componentAccessToken = $componentAccessTokenRow['info']['access_token'];
$row = json_encode(array(
'component_appid' => $this->appid
));
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token='.$componentAccessToken;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $row);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$output = curl_exec($ch);
curl_close($ch);
$returnArray = array(
'code' => 1,
'info' => json_decode($output, true)
);
}else{
$returnArray = array(
'code' => 0,
'info' => '获取component_access_token失败'
);
}
return $returnArray;
}
第三步、经过预受权码获取受权码
代码: 这是控制器中的方法
/**
* 发起受权页的体验URL获取预受权码
* @access public
*
*/
public function auth()
{
$url = '';
$wxAccessTokenModel = new \app\diuber\model\WxAccessToken();
//获取预受权码
$preAuthCodeRow = $wxAccessTokenModel->getPreAuthCode();
if($preAuthCodeRow['code'] == 1){
if(!empty($preAuthCodeRow['info']['pre_auth_code'])){
$preAuthCode = $preAuthCodeRow['info']['pre_auth_code'];
//拼接获取预受权码的URL
$url = 'https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid='.$this->appId.'&pre_auth_code='.$preAuthCode.'&redirect_uri=https://xx.xxxx.com/xxxx/wx_third_plat/getAuthCode';
}
}
//传入前端的URL
$this->assign('url', $url);
return $this->fetch('auth');
}
前端 auth.html:
<a href="{$url}" id="authurl" style="display: inline;">
<img src="https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon_button3_1.png">
</a>
点击受权跳转到微信公众平台受权,用户扫描受权以后会跳回到你在auth方法中的redirect_uri,而且会带上受权auth_code,注意这里的auth_code是带在url中的须要用GET获取,
redirect_uri中的方法(https://xx.xxxx.com/xxxx/wx_third_plat/getAuthCode),代码以下:
/**
* 获取用户受权码getAuthCode
* @access public
*
*/
public function getAuthCode()
{
self::checkCompanyID();
$result = array();
//实例化WxAccessToken模型,须要用到这个model中的getMiniAppInfo方法
$wxAccessTokenModel = new \app\diuber\model\WxAccessToken();
if(!empty($_GET)){
if(!empty($_GET['auth_code'])){
$result = $wxAccessTokenModel->getMiniAppInfo($_GET['auth_code'], $this->companyId);
}
}
$this->redirect('adminSetting/index');
}
getMiniAppInfo方法:
/**
* 经过受权码换取小程序的接口调用凭据和受权信息并保存
* @param $companyId 公司编号 区分不一样小程序受权帐号
* @access public
*
*/
public function getMiniAppInfo($authCode, $companyId = 0)
{
$returnArray = array();
$wxComponentTicketModel = new \app\diuber\model\WxComponentTicket();
$wxAuthorizerModel = new \app\diuber\model\WxAuthorizer();
//获取ComponentAccessToken
$componentAccessTokenRow = self::getComponentAccessToken();
if($componentAccessTokenRow['code'] == 1){
$componentAccessToken = $componentAccessTokenRow['info']['access_token'];
if($authCode){
$row = json_encode(array(
'component_appid' => $this->appid,
'authorization_code' => $authCode
));
//经过受权码获取公众号或小程序的接口调用凭据和受权信息
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token='.$componentAccessToken;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $row);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output, true);
//判断受权信息而且存入数据库中
if(!empty($output['authorization_info'])){
if($companyId){
$output['authorization_info']['company_id'] = $companyId;
$authResult = $wxAuthorizerModel->setMiniAppInfo($output['authorization_info']);
if($authResult['code'] == 1){
$returnArray = array(
'code' => 1,
'info' => $output['authorization_info']
);
}else{
$returnArray = array(
'code' => 0,
'info' => 'create or update mini app cgi info fail'
);
}
}else{
$returnArray = array(
'code' => 1,
'info' => $output['authorization_info']
);
}
}else{
$returnArray = array(
'code' => 0,
'info' => 'not found authorization_info'
);
}
}else{
$returnArray = array(
'code' => 0,
'info' => 'not found $authCode'
);
}
}else{
$returnArray = array(
'code' => 0,
'info' => 'get component_access_token fail'
);
}
return $returnArray;
}
setMiniAppInfo方法:
/**
* 保存小程序的接口调用凭据和受权信息
* @access public
*
*/
public function setMiniAppInfo($data)
{
$returnArray = array();
if($data){
if(!empty($data['authorizer_appid']) && !empty($data['authorizer_access_token']) && !empty($data['authorizer_refresh_token']) && !empty($data['func_info']) && !empty($data['expires_in']) && !empty($data['company_id'])){
$result = '';
//判断用户是否已经受权过
$existInfo = self::get(array('authorizer_appid'=>$data['authorizer_appid']));
if($existInfo){
//已受权
$existInfo = $existInfo->toArray();
if((time() - $existInfo['check_time']) < 6800){
//受权时间已经超过6800秒,更新
$row = array(
'authorizer_appid' => $data['authorizer_appid'],
'authorizer_access_token' => $data['authorizer_access_token'],
'authorizer_refresh_token' => $data['authorizer_refresh_token'],
'func_info' => json_encode($data['func_info']),
'update_time' => date('Y-m-d H:i:s'),
'check_time' => ($existInfo['check_time'] + $data['expires_in']),
'company_id' => $data['company_id']
);
$result = self::update($row, array('id'=>$existInfo['id']));
}else{
//受权时间已经超过6800秒,不做操做
$result = '没有超时,不用更新';
}
}else{
//未受权,新增受权信息
$row = array(
'authorizer_appid' => $data['authorizer_appid'],
'authorizer_access_token' => $data['authorizer_access_token'],
'authorizer_refresh_token' => $data['authorizer_refresh_token'],
'func_info' => json_encode($data['func_info']),
'create_time' => date('Y-m-d H:i:s'),
'check_time' => (time() + $data['expires_in']),
'company_id' => $data['company_id']
);
$result = self::create($row);
}
if($result){
$returnArray = array(
'code' => 1,
'info' => '建立或者更新成功'
);
}
}else{
$returnArray = array(
'code' => 0,
'info' => 'data格式不正确'
);
}
}
return $returnArray;
}
到这里已经获取到公众号或者小程序的受权信息,包括受权小程序的appid:authorizer_appid、受权小程序的AccessToken:authorizer_access_token、受权小程序的刷新code:authorizer_refresh_token 以及受权给开发者的权限集列表,具体权限查看微信文档。注意这个受权AccessToken有效时间是7200秒因此须要作好刷新AccessToken的方法。
下一章会增长刷新受权AccessToken的方法,以及介绍一些第三方代小程序开发的功能。