一、邏輯步驟解析
步驟 1:第三方平台方獲取預授權碼(pre_auth_code)
步驟 2:引入用戶進入授權頁
第三方平台方可以在自己的網站中放置“微信公眾號授權”或者“小程序授權”的入口,或生成授權鏈接放置在移動網頁中,引導公眾號和小程序管理員進入授權頁。
方式一:授權注冊頁面掃碼授權
授權頁網址為:
https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=xxxx&pre_auth_code=xxxxx&redirect_uri=xxxx&auth_type=xxx。
參數 |
必填 |
參數說明 |
component_appid |
是 |
第三方平台方 appid |
pre_auth_code |
是 |
預授權碼 |
redirect_uri |
是 |
回調 URI |
auth_type |
否 |
要授權的帳號類型, 1 則商戶掃碼后,手機端僅展示公眾號、2 表示僅展示小程序,3 表示公眾號和小程序都展示。如果為未指定,則默認小程序和公眾號都展示。第三方平台開發者可以使用本字段來控制授權的帳號類型。 |
biz_appid |
否 |
指定授權唯一的小程序或公眾號 |
二、代碼實現
wx_tools 工具文件

/** * 以post方式提交xml到對應的接口url * @param string $url 提交地址 * @param string $param 需要post的xml數據 * @param bool $file 是否上傳文件 * @param bool|array $cert 是否需要證書,默認不需要 如果是數組代表有證書地址 請按以下格式 array('cert' => 'cert.pem', 'key' => 'key.pem', 'rootca' => 'rootca.pem'); * @param int $second * @return mixed */ public static function postCurl($url, $param, $file = false, $cert = false, $second = 30) { $curl = curl_init(); //設置超時 curl_setopt($curl, CURLOPT_TIMEOUT, $second); if (stripos($url, "https://") !== FALSE) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 } if (PHP_VERSION_ID >= 50500 && class_exists('\CURLFile')) { $is_file = true; } else { $is_file = false; if (defined('CURLOPT_SAFE_UPLOAD')) { curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false); } } if (is_string($param)) { $str_post = $param; } elseif ($file) { if ($is_file) { foreach ($param as $key => $val) { if (substr($val, 0, 1) == '@') { $param[$key] = new \CURLFile(realpath(substr($val, 1))); } } } $str_post = $param; } else { $post = array(); foreach ($param as $key => $val) { $post[] = $key . "=" . urlencode($val); } $str_post = join("&", $post); } //設置證書 todo 未驗證 if (is_array($cert)) { //請確保您的libcurl版本是否支持雙向認證,版本高於7.20.1 使用證書:cert 與 key 分別屬於兩個.pem文件 curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($curl, CURLOPT_SSLCERT, $cert['cert']); curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($curl, CURLOPT_SSLKEY, $cert['key']); //紅包使用 if (empty($cert['rootca'])) { curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($curl, CURLOPT_CAINFO, $cert['rootca']); } } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $str_post); $content = curl_exec($curl); $status = curl_getinfo($curl); if (intval($status["http_code"]) == 200) { curl_close($curl); // ApiLog::setMessage(\Yii::$app->session->get('request_base_api_log_id'),['url' => $url, 'message'=> $content], 1); return $content; } else { $error = curl_errno($curl); curl_close($curl); // $this->err_code = $error; // $this->err_msg = $this->curl_error[$error]; // ApiLog::setMessage(\Yii::$app->session->get('request_base_api_log_id'),['url' => $url, 'message'=> $content], 0); return false; } } /** * CURL GET 請求 * @param $url * @return bool|mixed */ public static function getCurl($url) { $curl = curl_init(); if (stripos($url, "https://") !== FALSE) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $content = curl_exec($curl); $status = curl_getinfo($curl); if (intval($status["http_code"]) == 200) { curl_close($curl); // ApiLog::setMessage(\Yii::$app->session->get('request_base_api_log_id'),['url' => $url, 'message'=> $content], 1); return $content; } else { $error = curl_errno($curl); curl_close($curl); file_put_contents('../web/logs/notify/error' . date('YmdHi') . '.txt', $error); // ApiLog::setMessage(\Yii::$app->session->get('request_base_api_log_id'),['url' => $url, 'message'=> $content], 0); // $this->err_code = $error; // $this->err_msg = $this->curl_error[$error]; return false; } }
1、獲取pre_auth_code(通過component_access_token)
2、獲取component_access_token(通過component_verify_ticek)
3、component_verify_tick(通過三方平台填寫后台授權回到地址【10分鍾微信推送】)
/** * 獲取component_access_token * @return bool|mixed */ public static function getComponentAccessToken() { if (\Yii::$app->cache->exists(self::ComponentAccessToken)) { return \Yii::$app->cache->get(self::ComponentAccessToken); } $app_id = \Yii::$app->params['app_id']; $app_secret = \Yii::$app->params['app_secret']; $component_verify_ticket = self::getComponentVerifyTicket(); $url = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token'; $data = [ 'component_appid' => $app_id, 'component_appsecret' => $app_secret, 'component_verify_ticket' => $component_verify_ticket ]; $json = null; $result = wx_tools::postCurl($url, wx_tools::jsonEncode($data)); if ($result) { $json = wx_tools::parseData($result); if (!$json) { return false; } } $component_access_token = $json['component_access_token']; $expire = $json['expires_in'] ? intval($json['expires_in']) : 7200; \Yii::$app->cache->set(self::ComponentAccessToken, $component_access_token, $expire * 0.9); return $component_access_token; } /** * 獲取預授權碼 */ public static function getPreAuthCode() { if (\Yii::$app->cache->exists(self::PreAuthCode)) { return \Yii::$app->cache->get(self::PreAuthCode); } $component_access_token = self::getComponentAccessToken(); $app_id = \Yii::$app->params['app_id']; $url = 'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=' . $component_access_token; $data = [ 'component_appid' => $app_id ]; $result = wx_tools::postCurl($url, wx_tools::jsonEncode($data)); $json = null; if ($result) { $json = wx_tools::parseData($result); if (!$json) { return false; } $pre_auth_code = $json['pre_auth_code']; $expires_in = $json['expires_in']; \Yii::$app->cache->set(self::PreAuthCode, $pre_auth_code, $expires_in * 0.9); return $pre_auth_code; } return false; }
三方授權事件代碼
/** * 三方授權事件接收 */ public function actionNotify() { // file_put_contents('../web/logs/notify/notify'.date('YmdHi').'.txt','微信服務器進來的'); $data = file_get_contents('php://input'); // file_put_contents('../web/logs/notify/data'.date('YmdHi').'.txt',$data); // file_put_contents('../web/logs/notify/get'.date('YmdHi').'.txt',json_encode($_GET)); if ($data) { $time_stamp = empty($_GET['timestamp']) ? "" : trim($_GET['timestamp']); $nonce = empty($_GET['nonce']) ? "" : trim($_GET['nonce']); $msg_sign = empty($_GET['msg_signature']) ? "" : trim($_GET['msg_signature']); if (!$time_stamp || !$nonce || !$msg_sign) { // Log::ERROR('缺少time_stamp,nonce,msg_sign中任一項'); exit; } $app_id = \Yii::$app->params['app_id']; $token = \Yii::$app->params['token']; $encodingAesKey = \Yii::$app->params['encoding_aes_key']; $wx_biz = new WXBizMsgCrypt($token, $encodingAesKey, $app_id); $response = ''; $err_code = $wx_biz->decryptMsg($msg_sign, $time_stamp, $nonce, $data, $response); if ($err_code == 0) { $response = Tools::xmlToArray($response); $info_type = $response['InfoType']; switch ($info_type) { case 'component_verify_ticket': // Log::INFO('create component_verify_ticket'); //保存到緩存 wx_auth::saveComponentVerifyTicket($response['ComponentVerifyTicket']); //TODO break; case 'authorized': //TODO break; case 'unauthorized'; //TODO 取消授權 WxPlatform::updateAuthStatus($response['AuthorizerAppid']); wx_auth::clearAuthorizerAccessToken($response['AuthorizerAppid']); break; case 'updateauthorized': //TODO break; } exit('success'); } else { ApiLog::setMessage(\Yii::$app->session->get(self::RequestBaseApiLogId), $data, 0); // Log::ERROR('解密失敗:' . $err_code); exit('fail'); } } ApiLog::setMessage(\Yii::$app->session->get(self::RequestBaseApiLogId), '非微信服務器操作', 0); // Log::ERROR('非微信服務器操作'); exit; }
4、生成頁面URL
/** * 公眾號授權三方平台頁面 * @return string */ public function actionBind() { $params='';//可以帶的參數 $redirect_uri = \Yii::$app->request->hostInfo . \Yii::$app->request->scriptUrl . '/public-signal/bind-call-back' . '?params=' . $params; $app_id = \Yii::$app->params['app_id']; $url = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=" . $app_id . "&pre_auth_code=" . $pre_auth_code . "&redirect_uri=" . $redirect_uri; return $this->render('index', [ 'url' => $url ]); }
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>授權頁</title>
</head>
<body>
<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>
</body>
</html>
/** * 公眾號授權三方平台回調地址 完成自己的業務功能 * @return string|void */ public function actionBindCallBack() { $request = \Yii::$app->request; $params = explode(',', $request->get('params')); $auth_code = $request->get('auth_code'); }