1. 一.
    2. 授权流程
    3. 1. 接收component_verify_ticket
    4. [1]微信服务器每隔10分钟会向第三方的消息接收地址推送一次component_verify_ticket,拿到后需要在本地做好存储;
    5. [2]微信第三方平台的消息是加密的(下图),需要进行解密才能获取需要的信息;
    6. [3]接收并解密消息,代码如下:
    7. /**
    8. * 授权事件接收URL
    9. */
    10. public function msg() {
    11. import("@.ORG.ArrayTool");
    12. import("@.ORG.Weixincrypt.WXBizMsgCrypt");
    13. $timestamp = empty($_GET ['timestamp']) ? '' : trim($_GET ['timestamp']);
    14. $nonce = empty($_GET ['nonce']) ? '' : trim($_GET ['nonce']);
    15. $msgSign = empty($_GET ['msg_signature']) ? '' : trim($_GET ['msg_signature']);
    16. $signature = empty($_GET ['signature']) ? '' : trim($_GET ['signature']);
    17. $encryptType = empty($_GET ['encrypt_type']) ? '' : trim($_GET ['encrypt_type']);
    18. $encryptMsg = file_get_contents('php://input');
    19. $wxData = C("platform_setting");
    20. $encodingAesKey = $wxData['encodingAesKey'];
    21. $token = $wxData['token'];
    22. $appId = $wxData['appId'];
    23. $Wxcrypt = new WXBizMsgCrypt($token, $encodingAesKey, $appId);
    24. $postArr = ArrayTool::xml2array($encryptMsg);
    25. $format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
    26. $fromXml = sprintf($format, $postArr['Encrypt']);
    27. //第三方收到公众号平台发送的消息
    28. $msg = '';
    29. $errCode = $Wxcrypt->decryptMsg($msgSign, $timestamp, $nonce, $fromXml, $msg); // 解密
    30. if ($errCode == 0) {
    31. $param = ArrayTool::xml2array($msg);
    32. switch ($param['InfoType']) {
    33. case 'component_verify_ticket' : // 授权凭证
    34. $componentVerifyTicket = $param['ComponentVerifyTicket'];
    35. S('component_verify_ticket_' . $appId, $componentVerifyTicket);
    36. break;
    37. case 'unauthorized' : // 取消授权
    38. break;
    39. case 'authorized' : // 授权
    40. break;
    41. case 'updateauthorized' : // 更新授权
    42. break;
    43. }
    44. }
    45. exit("success");
    46. }
    47. 2.获取component_access_token
    48. [1]每个令牌是存在有效期(2小时)的,且令牌的调用不是无限制的,请第三方平台做好令牌的管理,在令牌快过期时(比如1小时50分)再进行刷新。所以要对component_access_token做好本地缓存,代码如下:
    49. $wxData = C("setting");
    50. //1. 取得component_verify_ticket
    51. $vt = S('component_verify_ticket_' . $wxData['appId']);
    52. $at = S('component_access_token_' . $wxData['appId']);
    53. //2. 获取第三方平台component_access_token
    54. if (empty($at) && !empty($vt)) {
    55. $url2 = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
    56. $post = array();
    57. $post['component_appid'] = $wxData['appId'];
    58. $post['component_appsecret'] = $wxData['appSecret'];
    59. $post['component_verify_ticket'] = $vt;
    60. $return2 = $this->curlPost($url2, $post);
    61. if (isset($return2['component_access_token'])) {
    62. $at = $return2['component_access_token'];
    63. S('component_access_token_' . $wxData['appId'], $at, 6600); //缓存1小时50分钟 = 6600秒
    64. } else {
    65. return false;
    66. }
    67. }
    68. 3.获取pre_auth_code(注意这是预授权码,不是授权码):
    69. $wxData = C('platform_setting');
    70. $appId = $wxData['appId'];
    71. $HT = new HttpTool();
    72. $at = $HT->getComponentAccessToken();
    73. if ($at) {
    74. //3.获取预授权码pre_auth_code
    75. $url3 = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token={$at}";
    76. $post = array();
    77. $post['component_appid'] = $appId;
    78. $return3 = $HT->curlPost($url3, $post);
    79. if (isset($return3['pre_auth_code'])) {
    80. $preauthcode = $return3['pre_auth_code'];
    81. $redirectUrl = C('site_url') . U("User/App/setauth", array('uid' => $uid));
    82. $weixinUrl = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid={$appId}&pre_auth_code={$preauthcode}&redirect_uri={$redirectUrl}";
    83. redirect($weixinUrl);
    84. exit;
    85. }
    86. }
    87. $this->error("亲, 授权失败了!");
    88. 4.使用授权码换取公众号的接口调用凭据和授权信息:
    89. //1. 使用授权码换取公众号的接口调用凭据和授权信息
    90. import("@.ORG.HttpTool");
    91. $HT = new HttpTool();
    92. $wxData = C('platform_setting');
    93. $caccessToken = $HT->getComponentAccessToken();
    94. $url1 = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token={$caccessToken}";
    95. $post = array();
    96. $post['component_appid'] = $wxData['appId'];
    97. $post['authorization_code'] = $authcode;
    98. $return = $HT->curlPost($url1, $post);
    99. if (isset($return['authorization_info'])) {
    100. $authinfo = $return['authorization_info'];
    101. $authid = $authinfo['authorizer_appid'];
    102. $accessToken = $authinfo['authorizer_access_token'];
    103. $refreshToken = $authinfo['authorizer_refresh_token'];
    104. //$funcInfo = $authinfo['func_info'];
    105. //2. 获取授权方的公众号帐号基本信息
    106. $url2 = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token={$caccessToken}";
    107. $post = array();
    108. $post['component_appid'] = $wxData['appId'];
    109. $post['authorizer_appid'] = $authid;
    110. $return2 = $HT->curlPost($url2, $post);
    111. if (isset($return2['authorizer_info'])) {
    112. $wxinfo = $return2['authorizer_info'];
    113. $fcinfo = $return2['authorization_info'];
    114. $Wxuser = M("Wxuser");
    115. //是否已经存在
    116. $extFilter = array();
    117. $wxuser['uid'] = $uid;
    118. $extFilter['auth_appid'] = $fcinfo['authorizer_appid'];
    119. $isExt = $Wxuser->where($extFilter)->find();
    120. $wxuser = array();
    121. $wxuser['uid'] = $uid;
    122. $wxuser['token'] = $this->getToken();
    123. $wxuser['wxid'] = $wxinfo['user_name']; //原始ID
    124. $wxuser['wxname'] = $wxinfo['nick_name']; //昵称
    125. $wxuser['weixin_type'] = $wxinfo['service_type_info']['id']; //微信类型 授权方公众号类型,0代表订阅号,1代表由历史老帐号升级后的订阅号,2代表服务号
    126. $wxuser['weixin'] = $wxinfo['alias']; //微信号
    127. $wxuser['headerpic'] = $wxinfo['head_img']; //头像
    128. $wxuser['bind_type'] = 1;
    129. $wxuser['auth_appid'] = $fcinfo['authorizer_appid'];
    130. $wxuser['auth_access_token'] = $accessToken;
    131. $wxuser['auth_refresh_token'] = $refreshToken;
    132. $wxuser['auth_functions'] = json_encode($fcinfo['func_info']);
    133. $wxuser['auth_business_info'] = json_encode($wxinfo['business_info']);
    134. $wxuser['create_time'] = time();
    135. if ($isExt) {
    136. $sign = $Wxuser->where($extFilter)->save($wxuser);
    137. } else {
    138. $sign = $Wxuser->add($wxuser);
    139. if ($sign) {
    140. //添加功能模块
    141. $this->addfc($wxuser['token']);
    142. //记录公众号数量
    143. M('Users')->where(array('id' => $uid))->setInc('wechat_card_num');
    144. }
    145. }
    146. if ($sign) {
    147. redirect(C("site_url") . U('User/Index/index'));
    148. }
    149. }
    150. }
    151. $this->error("亲,获取授权信息失败!", U('User/Index/index'));
    152. 二. 全网发布
    153. 代码如下:
    154. /**
    155. * 公众号消息与事件接收URL
    156. */
    157. public function index() {
    158. $timestamp = empty($_GET['timestamp']) ? '' : trim($_GET['timestamp']);
    159. $nonce = empty($_GET['nonce']) ? '' : trim($_GET ['nonce']);
    160. $msgSign = empty($_GET['msg_signature']) ? '' : trim($_GET['msg_signature']);
    161. $signature = empty($_GET['signature']) ? '' : trim($_GET['signature']);
    162. $encryptType = empty($_GET['encrypt_type']) ? '' : trim($_GET['encrypt_type']);
    163. $openid = trim($_GET['openid']);
    164. import("@.ORG.ArrayUtil");
    165. import("@.ORG.Weixincrypt.WXBizMsgCrypt");
    166. $input = file_get_contents('php://input');
    167. $paramArr = ArrayUtil::xml2array($input);
    168. //$this->logPrint($paramArr);
    169. //$this->logPrint($_GET);
    170. //解密
    171. $wxData = C("platform_setting");
    172. $encodingAesKey = $wxData['encodingAesKey'];
    173. $token = $wxData['token'];
    174. $appId = $wxData['appId'];
    175. $Wxcrypt = new WXBizMsgCrypt($token, $encodingAesKey, $appId);
    176. $format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
    177. $fromXml = sprintf($format, $paramArr['Encrypt']);
    178. $errCode = $Wxcrypt->decryptMsg($msgSign, $timestamp, $nonce, $fromXml, $toXml); // 解密
    179. $this->logPrint($toXml);
    180. if ($errCode == 0) {
    181. $param = ArrayUtil::xml2array($toXml);
    182. $keyword = isset($param['Content']) ? trim($param['Content']) : '';
    183. // 案例1 - 发送事件
    184. if (isset($param['Event']) && $paramArr['ToUserName'] == 'gh_3c884a361561') {
    185. $contentStr = $param ['Event'] . 'from_callback';
    186. }
    187. // 案例2 - 返回普通文本
    188. elseif ($keyword == "TESTCOMPONENT_MSG_TYPE_TEXT") {
    189. $contentStr = "TESTCOMPONENT_MSG_TYPE_TEXT_callback";
    190. }
    191. // 案例3 - 返回Api文本信息
    192. elseif (strpos($keyword, "QUERY_AUTH_CODE:") !== false) {
    193. import("@.ORG.HttpTool");
    194. $authcode = str_replace("QUERY_AUTH_CODE:", "", $keyword);
    195. $contentStr = $authcode . "_from_api";
    196. $HT = new HttpTool();
    197. $authDetail = $HT->getAccessTokenByAuthCode($authcode);
    198. $accessToken = $authDetail['authorizer_access_token'];
    199. $HT->sendFansText($accessToken, $param['FromUserName'], $contentStr);
    200. //$tokenInfo = WechatOpenApiLogic::getAuthorizerAccessTokenByAuthCode($ticket);
    201. //$param ['authorizerAccessToken'] = $tokenInfo ['authorization_info'] ['authorizer_access_token'];
    202. //self::sendServiceMsg($param['FromUserName'], $param['ToUserName'], 1, $contentStr); // 客服消息接口
    203. return 1;
    204. }
    205. $result = '';
    206. if (!empty($contentStr)) {
    207. $xmlTpl = "<xml>
    208. <ToUserName><![CDATA[%s]]></ToUserName>
    209. <FromUserName><![CDATA[%s]]></FromUserName>
    210. <CreateTime>%s</CreateTime>
    211. <MsgType><![CDATA[text]]></MsgType>
    212. <Content><![CDATA[%s]]></Content>
    213. </xml>";
    214. $result = sprintf($xmlTpl, $param['FromUserName'], $param['ToUserName'], time(), $contentStr);
    215. if (isset($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') { // 密文传输
    216. $wxData = C("platform_setting");
    217. $msgCryptObj = new WXBizMsgCrypt($wxData['token'], $wxData['encodingAesKey'], $wxData['appId']);
    218. $encryptMsg = '';
    219. $msgCryptObj->encryptMsg($result, $_GET['timestamp'], $_GET['nonce'], $encryptMsg);
    220. $result = $encryptMsg;
    221. }
    222. }
    223. echo $result;
    224. }
    225. }