第一步,經過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的方法,以及介紹一些第三方代小程序開發的功能。