分享一下微信的第三方平臺(tái)授權(quán)吧,中間還是有挺多坑的唤殴,開(kāi)發(fā)前一定要仔細(xì)的看幾遍文檔
一哺窄、首先在微信申請(qǐng)成為第三方捐下,流程按著微信提示的走就好了
二、開(kāi)發(fā)授權(quán)
1萌业、接收 微信的推送 component_verify_ticket 協(xié)議
在第三方平臺(tái)創(chuàng)建審核通過(guò)后坷襟,微信服務(wù)器會(huì)向其“授權(quán)事件接收URL”每隔10分鐘定時(shí)推送component_verify_ticket。第三方平臺(tái)方在收到ticket推送后也需進(jìn)行解密(詳細(xì)請(qǐng)見(jiàn)【消息加解密接入指引】)生年,接收到后必須直接返回字符串success婴程。
點(diǎn)進(jìn)【消息加解密接入指引】后,下載SDK包抱婉,在項(xiàng)目中引入排抬,我就用ThinkPHP5舉例了
將php包放到 /extend/Wxapi/
<?php
/**
* 三方平臺(tái)微信授權(quán)
*
*/
namespace app\home\controller\api;
use think\Controller;
use think\Db;
use Endroid\QrCode\QrCode;
use think\Loader;
Loader::import('Wxapi.wx', EXTEND_PATH, '.BizMsgCrypt.php');
class Wxapi extends Controller
{
function __construct()
{
parent::__construct();
$this->token = '自己的token';
$this->encodingAesKey = '自己的encodingAesKey ';
$this->appid = 'appid';
$this->appsecret = 'appsecret';
}
//1懂从、接收component_verify_ticket協(xié)議
public function Accredit()
{
$token = $this->token;
$encodingAesKey = $this->encodingAesKey;
$appId = $this->appid;
$pc = new \WXBizMsgCrypt($token, $encodingAesKey, $appId);
$timeStamp = empty($_GET['timestamp']) ? "" : trim($_GET['timestamp']) ;
$nonce = empty($_GET['nonce']) ? "" : trim($_GET['nonce']) ;
$msg_sign = empty($_GET['msg_signature']) ? "" : trim($_GET['msg_signature']) ;
$encryptMsg = file_get_contents('php://input');
echo 'success';
$xml_tree = new \DOMDocument();
$xml_tree->loadXML($encryptMsg);
$array_e = $xml_tree->getElementsByTagName('Encrypt');
$encrypt = $array_e->item(0)->nodeValue;
$format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
$from_xml = sprintf($format, $encrypt);
$this->logResult('/form.log', $from_xml);
// 第三方收到公眾號(hào)平臺(tái)發(fā)送的消息
$msg = '';
$errCode = $pc->decryptMsg($msg_sign, $timeStamp, $nonce, $from_xml, $msg);
if ($errCode == 0) {
//print("解密后: " . $msg . "\n");
$xml = new \DOMDocument();
$xml->loadXML($msg);
$array_e = $xml->getElementsByTagName('ComponentVerifyTicket');
$component_verify_ticket = $array_e->item(0)->nodeValue;
$arr['wxtoken'] = $component_verify_ticket;
$arr['type'] = 1;
$arr['effective'] = time()+300;
$res = Db::table('wxtoken')->where('id',1)->update($arr);
file_put_contents(EXTEND_PATH.'/ticket.log', $component_verify_ticket);
// $this->logResult('/msgmsg.log','解密后的component_verify_ticket是:'.$component_verify_ticket);
$msgObj = simplexml_load_string($msg, 'SimpleXMLElement', LIBXML_NOCDATA);
$content = trim($msgObj->Content);
//第三方平臺(tái)全網(wǎng)發(fā)布檢測(cè)普通文本消息測(cè)試
if (strtolower($msgObj->MsgType) == 'text' && $content == 'TESTCOMPONENT_MSG_TYPE_TEXT') {
$toUsername = trim($msgObj->ToUserName);
if ($toUsername == 'gh_3c884a361561') {
$content = 'TESTCOMPONENT_MSG_TYPE_TEXT_callback';
echo $this->responseText($msgObj, $content);
}
}
//第三方平臺(tái)全網(wǎng)發(fā)布檢測(cè)返回api文本消息測(cè)試
if (strpos($content, 'QUERY_AUTH_CODE') !== false) {
$toUsername = trim($msgObj->ToUserName);
if ($toUsername == 'gh_3c884a361561') {
$query_auth_code = str_replace('QUERY_AUTH_CODE:', '', $content);
$params = $this->dedeLogic->api_query_auth($query_auth_code);
$authorizer_access_token = $params['authorization_info']['authorizer_access_token'];
$content = "{$query_auth_code}_from_api";
$this->sendServiceText($msgObj, $content, $authorizer_access_token);
}
}
return 'success';
} else {
$this->logResult('/error.log','解密后失敗:'.$errCode);
print($errCode . "\n");
}
}
2蹲蒲、獲取第三方平臺(tái)component_access_token
/**
* 2番甩、獲取第三方平臺(tái)component_access_token
*/
function GetComponent(){
$verify_ticket = Db::table('wxtoken')->where('id',1)->find();
$component =$verify_ticket['wxtoken'];
$url = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
$data = array(
"component_appid"=>$this->appid,
"component_appsecret"=>$this->appsecret,
"component_verify_ticket"=>$component
);
$send_result = $this->httpRequest($url,'POST',json_encode($data));
$send_result = json_decode($send_result,true);
$component_access_token = empty($send_result['component_access_token']) ? "" : trim($send_result['component_access_token']);
$arr['wxtoken'] = $component_access_token;
$arr['type'] = 2;
$arr['effective'] = time()+6600;
$res = Db::table('wxtoken')->where('id',2)->update($arr);
// var_dump($send_result);
return $component_access_token;
}
3、獲取預(yù)授權(quán)碼pre_auth_code
/**
* 3届搁、獲取預(yù)授權(quán)碼pre_auth_code
*/
private function Precode(){
$data = Db::table('wxtoken')->where('id','3')->find();
if(!empty($data) && $data['effective']<=time()){
$component = Db::table('wxtoken')->where('id',2)->find();
if(!empty($component) && $component['effective']>time()){
$token = $component['wxtoken'];
}else{
$token = $this->GetComponent();
}
$url = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token={$token}";
$data = array(
"component_appid"=>$this->appid
);
$send_result = $this->httpRequest($url,'POST',json_encode($data));
$send_result = json_decode($send_result,true);
$arr['wxtoken'] = empty($send_result['pre_auth_code']) ? '': trim($send_result['pre_auth_code']);
$arr['type'] = 3;
$arr['effective'] = time()+600;
$res = Db::table('wxtoken')->where('id','3')->update($arr);
// var_dump($send_result);
return $arr['wxtoken'];
}else{
return $data['wxtoken'];
}
}
4缘薛、使用預(yù)授權(quán)碼換取用戶授權(quán)碼
// 4、第四步前一半卡睦,返回用戶授權(quán)二維碼
public function qrcode($vid)
{
$appid = $this->appid;
$precode = $this->Precode();
$redirect_uri = 'xxxx.com/home/miniapp/succeed?vid='.$vid; //授權(quán)后回調(diào)傳值地址
$qrCode=new QrCode();
//電腦網(wǎng)頁(yè)端驗(yàn)證
$url = 'https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid='.$appid.'&pre_auth_code='.$precode.'&redirect_uri='.$redirect_uri.'&auth_type=2';
return $url;
}
/**
* 4宴胧、第四步的后一半,用戶授權(quán)后回調(diào)地址
* 授權(quán)后回調(diào)URI表锻,得到授權(quán)碼(authorization_code)和過(guò)期時(shí)間
* 第三方平臺(tái)獲取到的該小程序授權(quán)的authorizer_access_token
*/
function Succeed(){
$map['vid'] = input('get.vid');
$authorization_code = empty($_GET['auth_code']) ? "" : trim($_GET['auth_code']);
$expires_in = empty($_GET['expires_in']) ? '' : (trim($_GET['expires_in'])+time());
$map['wxtoken'] = $authorization_code;
$map['effective'] = $expires_in;
//這里是把授權(quán)信息存儲(chǔ)起來(lái)
$res = Db::table('wxtoken')->where('vid',$map['vid'])->find();
if($res){
$test = Db::table('wxtoken')->where('vid',$map['vid'])->update($map);
}else{
$test = Db::table('wxtoken')->insert($map);
}
if($res && $test){
$result = '授權(quán)成功';
}else{
$result = '授權(quán)失敗';
}
$this->assign('result',$result);
return $this->fetch('accredit');
}
5恕齐、使用授權(quán)碼換取公眾號(hào)或小程序的接口調(diào)用憑據(jù)和授權(quán)信息
/**
* 5、使用授權(quán)碼換取公眾號(hào)或小程序的接口調(diào)用憑據(jù)和授權(quán)信息
* 微信授權(quán)文檔中4
* 獲取authorizer_access_token和authorizer_refresh_token
*/
public function get_authorizer_token($vid){
if(empty($vid)){return false; }
//第三方平臺(tái)appid
$appid = $this->appid;
//獲取用戶授權(quán)碼 authorization_code
$auth_code_value = Db::table('wxtoken')->where('vid',$vid)->find();
//獲取 component_access_token
$component = Db::table('wxtoken')->where('id',2)->find();
if(!empty($component) && $component['effective']>time()){
$token = $component['wxtoken'];
}else{
$token = $this->GetComponent();
}
// var_dump($auth_code_value);die;
if(empty($auth_code_value)) {
return 1; //沒(méi)有授權(quán)碼
}
if($auth_code_value['effective'] < time()){
//授權(quán)碼過(guò)期 , 用令牌去刷新authorizer_access_token
$authorizer_access_token = $this->refresh_code($appid,$token);
return $authorizer_access_token;
}else{
$auth_code_value = $auth_code_value['wxtoken'];
}
$url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=$token";
$data = array(
"component_appid"=>"$appid",
"authorization_code"=>"$auth_code_value"
);
$authorizerData = $this->httpRequest($url,'POST',json_encode($data));
//授權(quán)成功后json串
// $authorizerData = '{"authorization_info":{"authorizer_appid":"wxc756dcabc3f745a0","authorizer_access_token":"16_VTixr87SXLN0VElDCXLEQatq7aPoG_JXAaWoAnGfe8eFeZELbx8PmVbswUwqG9UQSh3BYPinvUejWlG1JKlaOttOX3h9EGgV5KTrggN3bRpU4EQUpzqh-xGTNdUMQousIg0adK8MYePXwRBOPFTdAEDCSG","expires_in":7200,"authorizer_refresh_token":"refreshtoken@@@-XgUNiQhWcCugsXx9Dh-tOPQK_JL-o3yepI4wto2wmw","func_info":[{"funcscope_category":{"id":17}},{"funcscope_category":{"id":18},"confirm_info":{"need_confirm":0,"already_confirm":0,"can_confirm":0}},{"funcscope_category":{"id":19}},{"funcscope_category":{"id":25},"confirm_info":{"need_confirm":0,"already_confirm":0,"can_confirm":0}},{"funcscope_category":{"id":30},"confirm_info":{"need_confirm":0,"already_confirm":0,"can_confirm":0}},{"funcscope_category":{"id":31},"confirm_info":{"need_confirm":0,"already_confirm":0,"can_confirm":0}},{"funcscope_category":{"id":37}},{"funcscope_category":{"id":40}}]}}';
$test = json_decode($authorizerData,true);
if(array_key_exists('authorization_info', $test)){
$test = $test['authorization_info'];
$arr['component_appid'] = $appid;
$arr['authorizer_appid'] = $test['authorizer_appid'];
$arr['authorizer_access_token'] = $test['authorizer_access_token'];
$arr['expires_in'] = intval($test['expires_in'])+time();//有效期2H
$arr['authorizer_refresh_token'] = $test['authorizer_refresh_token'];
$arr['func_info'] = '';
$res = Db::name('miniapp_accredit')->insert($arr);
return $test;
}else{
return false;
}
}
用戶授權(quán)的授權(quán)碼有效期為10分鐘瞬逊,過(guò)期后刷新
/**
* 用戶授權(quán)的授權(quán)碼有效期為10分鐘显歧,過(guò)期后刷新
* 獲取(刷新)授權(quán)公眾號(hào)或小程序的接口調(diào)用憑據(jù)(令牌)
* component_appid 第三方平臺(tái)appid
* authorizer_appid 授權(quán)方appid
* authorizer_refresh_token 授權(quán)方的刷新令牌
*/
public function refresh_code($appid,$token){
$tokens = Db::name('miniapp_accredit')->where('component_appid',$appid)->find();
if(empty($tokens)){
//沒(méi)有存放用戶刷新令牌确镊,只能重新授權(quán)
echo '沒(méi)有存放用戶刷新令牌士骤,只能重新授權(quán)';
return false;
}elseif($tokens['expires_in'] > time()){
//還在有效期
return $tokens;
}
$url = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=$token";
$data = array(
"component_appid"=>"$appid",
"authorizer_appid"=>$tokens['authorizer_appid'],
"authorizer_refresh_token"=>$tokens['authorizer_refresh_token'],
);
$authorizerData = $this->httpRequest($url,'POST',json_encode($data));
$test = json_decode($authorizerData,true);
if($test){
$arr['authorizer_access_token'] = $test['authorizer_access_token'];
$arr['expires_in'] = intval($test['expires_in'])+time();//有效期2H
$arr['authorizer_refresh_token'] = $test['authorizer_refresh_token'];
$res = Db::table('miniapp_accredit')->where('id',$tokens['id'])->update($arr);
unset($arr);
}
$test['authorizer_appid'] = $tokens['authorizer_appid'];
return $test;
}
CURL請(qǐng)求
/**
* CURL請(qǐng)求
* @param $url 請(qǐng)求url地址
* @param $method 請(qǐng)求方法 get post
* @param null $postfields post數(shù)據(jù)數(shù)組
* @param array $headers 請(qǐng)求header信息
* @param bool|false $debug 調(diào)試開(kāi)啟 默認(rèn)false
* @return mixed
*/
function httpRequest($url, $method="GET", $postfields = null, $headers = array(), $debug = false) {
$method = strtoupper($method);
$ci = curl_init();
/* Curl settings */
curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在發(fā)起連接前等待的時(shí)間,如果設(shè)置為0蕾域,則無(wú)限等待 */
curl_setopt($ci, CURLOPT_TIMEOUT, 7); /* 設(shè)置cURL允許執(zhí)行的最長(zhǎng)秒數(shù) */
curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
switch ($method) {
case "POST":
curl_setopt($ci, CURLOPT_POST, true);
if (!empty($postfields)) {
$tmpdatastr = is_array($postfields) ? http_build_query($postfields) : $postfields;
curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr);
}
break;
default:
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //設(shè)置請(qǐng)求方式 */
break;
}
$ssl = preg_match('/^https:\/\//i',$url) ? TRUE : FALSE;
curl_setopt($ci, CURLOPT_URL, $url);
if($ssl){
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https請(qǐng)求 不驗(yàn)證證書(shū)和hosts
curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不從證書(shū)中檢查SSL加密算法是否存在
}
//curl_setopt($ci, CURLOPT_HEADER, true); /*啟用時(shí)會(huì)將頭文件的信息作為數(shù)據(jù)流輸出*/
curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的數(shù)量拷肌,這個(gè)選項(xiàng)是和CURLOPT_FOLLOWLOCATION一起使用的*/
curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ci, CURLINFO_HEADER_OUT, true);
/*curl_setopt($ci, CURLOPT_COOKIE, $Cookiestr); * *COOKIE帶過(guò)去** */
$response = curl_exec($ci);
$requestinfo = curl_getinfo($ci);
$http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
if ($debug) {
echo "=====post data======\r\n";
var_dump($postfields);
echo "=====info===== \r\n";
print_r($requestinfo);
echo "=====response=====\r\n";
print_r($response);
}
curl_close($ci);
return $response;
//return array($http_code, $response,$requestinfo);
}
喜歡的朋友可以點(diǎn)擊喜歡和收藏,如果轉(zhuǎn)載請(qǐng)注明出處http://www.reibang.com/p/dd6c4be503f0