這兩天作了微信開發平臺的開發,梳理下。。。
浙江百牛信息技術bainiu.ltd整理髮佈於博客園
先看看受權的流程:php
第一步:接收component_verify_ticket:
一、微信服務器每隔10分鐘會向第三方的消息接收地址推送一次component_verify_ticket,拿到後須要在本地作好存儲;
二、微信第三方平臺的消息是加密的(下圖),須要進行解密才能獲取須要的信息;
三、接收並解密消息,代碼以下:
- $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' );
- $pc = new WXBizMsgCrypt ( OPEN_MSG_VERIFY_TOKEN, OPEN_ENCRYPT_KEY, OPEN_APPID );
- $postArr = ArrayUtil::xml2array ( $encryptMsg ); // xml對象解析
- $format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
- $from_xml = sprintf ( $format, $postArr ['Encrypt'] );
- // 第三方收到公衆號平臺發送的消息
- $msg = '';
- $errCode = $pc->decryptMsg ( $msg_sign, $timeStamp, $nonce, $from_xml, $msg ); // 解密
- if ($errCode == 0) {
- $param = ArrayUtil::xml2array ( $msg );
- switch ($param ['InfoType']) {
- case 'component_verify_ticket' : // 受權憑證
- $component_verify_ticket = $param ['ComponentVerifyTicket'];
- $ret ['component_verify_ticket'] = $component_verify_ticket;
- file_put_contents ( OPEN_COMPONENT_VERIFY_TICKET_PATH, $component_verify_ticket ); // 緩存
- break;
- case 'unauthorized' : // 取消受權
- $status = 2;
- break;
- case 'authorized' : // 受權
- $status = 1;
- break;
- case 'updateauthorized' : // 更新受權
- break;
- }
- }
第二步:獲取component_access_token:
每一個令牌是存在有效期(2小時)的,且令牌的調用不是無限制的,請第三方平臺作好令牌的管理,在令牌快過時時(好比1小時50分)再進行刷新。因此要對component_access_token作好本地緩存,代碼以下:
第三步:獲取pre_auth_code(注意這是預受權碼,不是受權碼):
- $nowTime = time ();
- $getCache = false; // 是否從緩存獲取
- if (is_file ( OPEN_COMPONENT_ACCESS_TOKEN_PATH )) {
- $cacheJson = file_get_contents ( OPEN_COMPONENT_ACCESS_TOKEN_PATH );
- if (json_decode ( $cacheJson )) {
- $cacheArr = json_decode ( $cacheJson, true );
- if (! empty ( $cacheArr ['component_access_token'] ) && $cacheArr ['expires_in'] > $nowTime + 120) {
- $ret ['errCode'] = 0;
- $ret ['component_access_token'] = $cacheArr ['component_access_token'];
- $getCache = true;
- }
- }
- }
- // 若本地緩存不存在或已失效,則從微信服務器從新獲取
- if (! $getCache) {
- $url = WeixinApiLang::$url ['component_token'];
- $ticket = file_get_contents ( OPEN_COMPONENT_VERIFY_TICKET_PATH );
- $data = '{
- "component_appid":"' . OPEN_APPID . '",
- "component_appsecret":"' . OPEN_APPSECRET . '",
- "component_verify_ticket":"' . $ticket . '"
- }';
- $ret = self::requestWeixinAPI ( $url, $data );
- // 緩存到本地
- if (isset ( $ret ['component_access_token'] )) {
- $cacheArr = array ();
- $cacheArr ['component_access_token'] = $ret ['component_access_token'];
- $ret ['expires_in'] += $nowTime;
- $cacheArr ['expires_in'] = $ret ['expires_in'];
- file_put_contents ( OPEN_COMPONENT_ACCESS_TOKEN_PATH, json_encode ( $cacheArr ) );
- }
- }
第四步:使用受權碼換取公衆號的接口調用憑據和受權信息:
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=' . $accessToken;
- $data = '{
- "component_appid":"' . OPEN_APPID . '"
- }';
- $ret = self::requestWeixinAPI ( $url, $data );
受權碼authorization_code是用戶「確認受權」後,微信回調時返回的。代碼以下:到此,受權流程就走完了。。。
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=' . $accessToken;
- $data = '{
- "component_appid":"' . OPEN_APPID . '",
- "authorization_code": "' . $authorization_code . '"
- }';
- $ret = self::requestWeixinAPI ( $url, $data );
接着看看全網發佈的測試用例怎麼作:
一、模擬粉絲觸發專用測試公衆號的事件,並推送事件消息到專用測試公衆號,第三方平臺方開發者須要提取推送XML信息中的event值,並在5秒內當即返回按照下述要求組裝的文本消息給粉絲;
二、模擬粉絲髮送文本消息給專用測試公衆號,第三方平臺方需根據文本消息的內容進行相應的響應;
三、模擬粉絲髮送文本消息給專用測試公衆號,第三方平臺方需在5秒內返回空串代表暫時不回覆,而後再當即使用客服消息接口發送消息回覆粉絲。
代碼以下:全網發佈接入檢測:
- $xmlTpl = "<xml>
- <ToUserName><![CDATA[%s]]></ToUserName>
- <FromUserName><![CDATA[%s]]></FromUserName>
- <CreateTime>%s</CreateTime>
- <MsgType><![CDATA[text]]></MsgType>
- <Content><![CDATA[%s]]></Content>
- </xml>";
- $keyword = isset ( $param ['Content'] ) ? trim ( $param ['Content'] ) : '';
- if(isset($param ['Event']) && $param ['ToUserName'] == 'gh_3c884a361561'){ // 案例1
- $contentStr = $param ['Event'] . 'from_callback';
- }elseif ($keyword == "TESTCOMPONENT_MSG_TYPE_TEXT") { // 案例2
- $contentStr = "TESTCOMPONENT_MSG_TYPE_TEXT_callback";
- } elseif (strpos ( $keyword, "QUERY_AUTH_CODE:" ) !== false) { // 案例3
- $ticket = str_replace ( "QUERY_AUTH_CODE:", "", $keyword );
- $contentStr = $ticket . "_from_api";
- $tokenInfo = WechatOpenApiLogic::getAuthorizerAccessTokenByAuthCode ( $ticket );
- $param ['authorizerAccessToken'] = $tokenInfo ['authorization_info'] ['authorizer_access_token'];
- self::sendServiceMsg ( $param ['FromUserName'], $param ['ToUserName'], 1, $contentStr ); // 客服消息接口
- return 1;
- }
- $result = '';
- if (! empty ( $contentStr )) {
- $result = sprintf ( $xmlTpl, $param ['FromUserName'], $param ['ToUserName'], time (), $contentStr );
- if (isset ( $_GET ['encrypt_type'] ) && $_GET ['encrypt_type'] == 'aes') { // 密文傳輸
- $msgCryptObj = new WXBizMsgCrypt ( OPEN_MSG_VERIFY_TOKEN, OPEN_ENCRYPT_KEY, OPEN_APPID );
- $encryptMsg = '';
- $msgCryptObj->encryptMsg ( $result, $_GET ['timestamp'], $_GET ['nonce'], $encryptMsg );
- $result = $encryptMsg;
- }
- }
寫的不是很詳細,有疑問留言。。。