第三方企业号对接工作
第三方企业号对接, 大概做了有一个月的时间, 过程还是非常艰辛的, 遇到了很多坑, 从不明所以, 到流程的理解的一个过程, 网上大多数的过程都很过程化, 把官方文档一贴, 基本上作用不大, 有几篇有帮助的, 但是忘记在哪里找到的了, 再者,
微信第三方文档的挂脸型和跳跃性非常强, 要串起来自我感觉还是挺费劲的, 如此, 简单的记录一下整体的对接流程和一些概念性的东西
成为第三方服务商, 首先必须是一个实体主体, 截止到目前, 微信不允许个人开发者测试开发第三方资源, 本文会引用大量官方文档原话, 就不做出特殊标记了,
在这里, 第三方这个此非常容易造成混淆, 一下称第三方服务商简称为服务商, 使用服务商提供服务的企业, 称为普通企业
按照微信官方的流程
一, 首先应用提供商注册应用
- 1 注册成为第三方应用提供商 — 就是提交一些作为第三方服务商的信息, 这个真的看看文档一共没几行
- 2 创建应用套件
- 3 在应用套件里添加应用
- 4 应用套件变更
针对第二点, 创建应用套件, (分两类 通讯录套件和普通应用套件)
通讯录套件: 用于第三方维护企业通讯录的场景。此类套件对企业的通讯录拥有根部门的修改权限,但无读权限。为避免通讯录被多方写乱的问题,一家企业只能授权一个通讯录套件。额外的,通讯录套件可包括最多一个普通应用
普通应用套件: 套件可包含最多10个应用,应用具有读通讯录、发消息等权限 ,
这里需要注意的是, 通讯录套件, 是套件对普通企业的通讯录具有修改权限, 然后通讯录套件下允许有一个应用, 这个应用其实和普通应用套件的应用是一样的
关于套件(以及套件下应用)的授权, 分两种, 授权方式的作用在于区分应用套件是否可以直接从企业号第三方官网发起授权,线上自助注册授权使用是指该应用套件可以直接从企业号第三方官网发起授权,而不跳转服务商网站,该类型的应用套件还可以支持移动端发起应用套件授权;服务商辅助授权使用是指该应用套件必须跳转服务商网站,从服务商网站发起应用套件的授权,该类型的应用套件不支持移动端发起应用套件授权
用我的话说就是一种必须要到服务商那边才能发起授权, 另一种在微信企业号后台搜出来直接授权就可以了
套件开发信息, 直接贴官方的
开发信息:
套件参数内容 | 说明 |
---|---|
发起授权域名 | 在该域名下发起的授权请求才可被通过,企业点击授权链接时,企业号会检查该域名是否已登记。 |
授权完成回调域名 | 在第三方应用授权流程中,授权成功后会302跳转到该域名下的url,返回临时code。你需用此code换取永久授权码。请尽量将此域名与发起授权域名保持一致。 |
系统事件接收URL | 系统将会把此套件的授权变更事件以及ticket参数推送给此URL,ticket说明详见API接口说明。(填写URL时需要正确响应微信验证URL的请求,具体说明请阅读“回调模式”) |
Token | 可任意填写,用于生成签名,校验回调请求的合法性。后续所有托管的企业产生的回调消息都使用该值来计算签名。 |
EncodingAESKey | 回调消息加解密参数,是AES密钥的Base64编码,用于解密回调消息内容对应的密文。后续所有托管的企业产生的回调消息都使用该值来解密。 |
应用套件ID | 应用套件的编号,相关的接口调用需要使用,由系统生成,不可更改。 |
应用套件secret | 应用套件的密钥,相关的接口调用需要使用。 |
白名单IP列表 | 应用套件调用企业号第三方应用API时的合法IP列表,只有白名单内的IP才能正常调用企业号API,后续IP若有修改,需要及时进行列表更新。 |
创建完成之后,系统会告知开发者该应用套件的Suiteid和Suitesecret。(详见第三方应用接口说明)
发起授权域名,授权完成回调域名,保持一致就行了,
系统时间接收URL这个非常重要比如 http://xxx.com/wx/api/index?corpid=$CORPID$ 微信给服务商推送信息的时候, 会带着服务商的corpid参数, 另, 这个url就相当于公众号配置的服务器url
token, EncodingAESKey没什么好说的, 随机生成然后就别变了, 记录下来就行了
应用套件ID和应用套件secret 套件新建成功后就由微信官方分配, 不可变更, 应用套件ID, 用到的地方非常多
第三点
套件添加应用
基本信息部分, 注意一下
通讯录权限等级,(建议选择通讯录基本信息只读)
通讯录权限范围(建议选用需要额外通讯录范围, 因为我们是服务商, 自然希望我们有最大的获得权限)
开发信息
CallbackURL 这个和套件的系统回调一致, 也要能相应token的加密
新建应用完成后再回来看应用的开发信息, 有个agentid, 这只是一个当前应用在套件里的一个顺序id, 应该是自增长的, 到现在为止还不知道有什么用
针对创建套件和创建套件应用, 这时就需要使用到一些代码了,如下
1 <?php 2 3 namespace Wx\Controller; 4 5 use Common\Common\LogException; 6 use Common\Common\WxApi; 7 use Common\Common\Utils\AES256; 8 use Common\Common\Service\AppService; 9 10 class ApiController extends BaseController 11 { 12 13 //套件的EncodingAESKey 14 private $encoding_aes_key; 15 //套件的Token 16 private $token; 17 //服务商的企业号corpid,不要问我在哪, 百度里面一把 18 private $corp_id; 19 //这里配置多个是为了多套件授权时, 并不知道到底哪个套件来的, 或者你可以再封装一个类, 每个套件的系统回调地址都不一样, 20 //这就看你也许需求,我这里就是用的循环每个套件信息, 有任何一个能得到正确的解析, 就算接入成功, 21 //其实你如果做过公众号, 知道这里很多人都不做验签, 直接返回了$_GET[\'echostr\'] 22 private $suite_id; //所有应用套件的应用id , 数据类型是array 23 private $wxcpt;//wx的消息解密类实例变量 24 25 public function _initialize() 26 { 27 header("Content-Type:text/html; charset=utf-8"); 28 $this->corp_id = \'wx04fsdeb6f6ef0w56\'; 29 $this->suite_id = array( 30 \'suiteid\'=>array(\'suite_token\'=>,\'suite_encoding_aes_key\'=>,), 31 \'suiteid\'=>array(\'suite_token\'=>,\'suite_encoding_aes_key\'=>,), 32 ); 33 } 34 35 public function index() 36 { 37 38 $get = $_GET; 39 $msg_sig = $get[\'msg_signature\']; 40 $time_stamp = $get[\'timestamp\']; 41 $nonce = $get[\'nonce\']; 42 $corpid = $get[\'corpid\']; 43 44 //如果是接入验证 45 if ($_SERVER[\'REQUEST_METHOD\'] === \'GET\' && isset($get[\'echostr\'])) { 46 47 $sVerifyEchoStr = $get[\'echostr\']; //单独获取校验echostr 48 $sEchoStr = ""; 49 foreach($this->suite_id as $k=>$v){ 50 $this->encoding_aes_key = $v[\'suite_encoding_aes_key\']; 51 $this->token = $v[\'suite_token\']; 52 $this->wxcpt = new WXBizMsgCrypt($this->token, $this->encoding_aes_key, $this->corp_id); 53 $err_code = $this->wxcpt->VerifyURL($msg_sig, $time_stamp, $nonce, $sVerifyEchoStr, $sEchoStr);//VerifyURL方法的最后一个参数是带取地址的, 54 //如果err_code === 0 的时候, $sEchoStr肯定不是"" 55 if ($err_code == 0) { 56 echo $sEchoStr; 57 exit; 58 } 59 } 60 LogException::write(\'注册套件失败\'); 61 } 62 //如果是微信推送消息 63 else if ($_SERVER[\'REQUEST_METHOD\'] === \'POST\') { 64 65 66 } 67 //如果是从服务商网站发起的授权, 授权完成后是get请求指直接302到服务商网站, 68 else if ($_SERVER[\'REQUEST_METHOD\'] === \'GET\' && isset($get[\'auth_code\'])) { 69 70 } 71 //其他请求, 不处理 72 else { 73 LogException::write("otherrequest\n\n"); 74 } 75 } 76 77 78 /** 79 * 解析内容, 第三方企业号专用 80 */ 81 public function exceDec($sMsg, $type = \'online\') 82 { 83 84 } 85 86 /** 87 * 在微信推送取消授权和变更授权操作时, 重新获得授权信息, 并更新授权应用, 会在exceDec方法中调用 88 */ 89 private function doChangeCancelAuth($suite_id, $auth_corp_id) 90 { 91 92 } 93 94 /** 95 * 解析事件推送和普通消息推送 96 * @param String(xml) $sMsg 97 */ 98 public function exceDecInfo($sMsg) 99 { 100 101 } 102 103 104 }
这个只是示例代码, 具体的还需要你来补充, 比如wx的验签类, 按照自己框架的载入方式, 然后看看怎么引用
单纯的对接的话, 其实现在已经完成了, 但是坑现在才刚刚开始
企业号管理员授权流程
这是官方文档使用的标题, 但是用本文的语言理解应该是普通企业管理员授权流程,
所以这里如上述的两种授权流程, 分为 线上自助注册授权使用, 就是普通企业在自己的企业微信后台直接授权安装一个应用,
从服务商网站发起授权流程
这块就不做太详细的介绍了, 直接看文档
http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E7%AE%A1%E7%90%86%E5%91%98%E6%8E%88%E6%9D%83%E6%B5%81%E7%A8%8B
接下来就是普通企业号和服务商授权应用或授权套件的过程, 这里面要在文档中的三个部分来回穿插着看
1.企业号管理员授权和流程, 这里面没有什么接口, 主要是让开发者明白一个过程
2.第三方应用接口说明, 关于服务商(第三方)获得普通企业的企业号信息, 最主要的还是access_token
3.第三方回调协议, 当普通企业在其后台对套件做了一些变动或者一些操作, 微信官方会给服务商推送一些消息, 包括
授权取消: 特指套件授权取消, 有两种方式触发这个回调, 普通企业直接对套件进行取消授权, 普通企业取消授权某个套件下的应用,如果这个应用是最后一个, 那么也会触发这个回调
授权变更: 应用授权取消, 应用授权权限变更, 都会触发这个回调,
授权成功推送auth_code — 在线上自助授权方式, 由于和服务商五交互, 所以这种授权完成之后, 会触发这个回调, 让服务商知道有那个企业授权了什么套件的什么应用,
推送suite_ticket协议: 这个接口微信会每十分钟给服务商推送一次, 服务商有多少套件就会同时推送多少个suite_ticket, 这东西只和套件有关,
推送suite_ticket这个接口非常重要, 没记错的话, 所有的套件授权都要获得suite_access_token, 获得suite_access_token的参数就又suite_ticket, 所以这个接口要先对接上
所以先就推送suite_ticket这接口开始我们的对接之坑
推送suite_ticket协议
微信服务器会向套件的“系统事件接收URL”定时(每十分钟)推送ticket:
POST数据示例
{ <xml> <SuiteId><![CDATA[wxfc918a2d200c9a4c]]></SuiteId> <InfoType> <![CDATA[suite_ticket]]></InfoType> <TimeStamp>1403610513</TimeStamp> <SuiteTicket><![CDATA[asdfasfdasdfasdf]]></SuiteTicket> </xml> }
应用提供商在收到ticket推送后需要返回字符串success。
字段说明
参数 | 说明 |
---|---|
SuiteId | 应用套件的SuiteId |
InfoType | suite_ticket |
TimeStamp | 时间戳 |
SuiteTicket | Ticket内容 |
为了加强安全性,postdata中的xml将使用应用套件申请时的加解密key来进行加密,具体请见“使用回调模式”,注意需要将corpid替换为suiteid,并忽略AgentID参数
上面的这一段是微信官方给出的对接文档, 要注意看最后的小字部分, postdata中的xml将使用应用套件申请时的加解密key来进行加密
所以在对接这个接口的时候, 对于php要使用file_get_contents(\’php://input\’, \’r\’); 你要是喜欢用别的方式也无所谓, 反正能获取出来就行
$postData = file_get_contents(\’php://input\’, \’r\’);
接收下来的数据是这样的
<xml> <ToUserName><![CDATA[toUser]]</ToUserName> <AgentID><![CDATA[toAgentID]]</AgentID> <Encrypt><![CDATA[msg_encrypt]]</Encrypt> </xml>
其中ToUserName对应的其实就是微信要发送给那个套件所以真实的数据就是<ToUserName><![CDATA[服务商某个套件的suite_id]]></ToUserName>
文档说注意需要将corpid替换为suiteid就是用这时候解析出来的这个toUserName标签来实例化解密类
如果是交互类的推送, ToUserName的内容就是corpid反正, 那还是用toUserName这个参数来实例化, 这时Agentid参数来确定请求的是哪个套件下的哪个应用,
通过DecryptMsg方法解密Encrypt会得到真实的请求信息代码如下
1 <?php 2 3 namespace Wx\Controller; 4 5 use Common\Common\LogException; 6 use Common\Common\WxApi; 7 use Common\Common\Utils\AES256; 8 use Common\Common\Service\AppService; 9 10 class ApiController extends BaseController 11 { 12 13 //套件的EncodingAESKey 14 private $encoding_aes_key; 15 //套件的Token 16 private $token; 17 //服务商的企业号corpid,不要问我在哪, 百度里面一把 18 private $corp_id; 19 //这里配置多个是为了多套件授权时, 并不知道到底哪个套件来的, 或者你可以再封装一个类, 每个套件的系统回调地址都不一样, 20 //这就看你也许需求,我这里就是用的循环每个套件信息, 有任何一个能得到正确的解析, 就算接入成功, 21 //其实你如果做过公众号, 知道这里很多人都不做验签, 直接返回了$_GET[\'echostr\'] 22 private $suite_id; //所有应用套件的应用id , 数据类型是array 23 private $wxcpt;//wx的消息解密类实例变量 24 25 public function _initialize() 26 { 27 header("Content-Type:text/html; charset=utf-8"); 28 $this->corp_id = \'wx04fsdeb6f6ef0w56\'; 29 $this->suite_id = array( 30 \'suiteid\'=>array(\'suiteid\'=>,\'suite_token\'=>,\'suite_encoding_aes_key\'=>,), 31 \'suiteid\'=>array(\'suiteid\'=>,\'suite_token\'=>,\'suite_encoding_aes_key\'=>,), 32 ); 33 } 34 35 public function index() 36 { 37 38 $get = $_GET; 39 $msg_sig = $get[\'msg_signature\']; 40 $time_stamp = $get[\'timestamp\']; 41 $nonce = $get[\'nonce\']; 42 $corpid = $get[\'corpid\']; 43 44 //如果是接入验证 45 if ($_SERVER[\'REQUEST_METHOD\'] === \'GET\' && isset($get[\'echostr\'])) { 46 47 $sVerifyEchoStr = $get[\'echostr\']; //单独获取校验echostr 48 $sEchoStr = ""; 49 foreach($this->suite_id as $k=>$v){ 50 $this->encoding_aes_key = $v[\'suite_encoding_aes_key\']; 51 $this->token = $v[\'suite_token\']; 52 $this->wxcpt = new WXBizMsgCrypt($this->token, $this->encoding_aes_key, $this->corp_id); 53 $err_code = $this->wxcpt->VerifyURL($msg_sig, $time_stamp, $nonce, $sVerifyEchoStr, $sEchoStr);//VerifyURL方法的最后一个参数是带取地址的, 54 //如果err_code === 0 的时候, $sEchoStr肯定不是"" 55 if ($err_code == 0) { 56 echo $sEchoStr; 57 exit; 58 } 59 } 60 LogException::write(\'注册套件失败\'); 61 } 62 //如果是微信推送消息 63 else if ($_SERVER[\'REQUEST_METHOD\'] === \'POST\') { 64 // post请求的密文数据 65 // $sReqData = HttpUtils.PostData(); 66 $sReqData = file_get_contents("php://input"); //必须通过输入流方式获取post数据, 数据头为{"Content-Type":"application/xml"} 67 $xml = new \DOMDocument(); 68 $xml->loadXML($sReqData); 69 $ToUserName = $xml->getElementsByTagName(\'ToUserName\')->item(0)->nodeValue;//其实就是目标套件的suiteid 70 $ToUserNameType = \'\'; 71 72 $sassInfo = array();//存储当前推送回调这个套件的信息, 用来实例化 73 foreach($this->suite_id as $k => $v){ 74 if($v[\'suite_id\'] == $ToUserName){ 75 $sassInfo = $v; 76 $ToUserNameType = \'sutieid\'; 77 break; 78 } 79 } 80 81 //和上面的实例化对比就体现出来这个用suite_ticket替换corpid 82 $this->wxcpt = new WXBizMsgCrypt($sassInfo[\'suite_token\'], $sassInfo[\'suite_encoding_aes_key\'], $ToUserName); 83 $err_code = -1; 84 $sMsg = ""; // 解析之后的明文 85 $err_code = $this->wxcpt->DecryptMsg($msg_sig, $time_stamp, $nonce, $sReqData, $sMsg);//解密方法内部对$sMsg进行赋值 86 if($err_code == 0){ 87 if ($ToUserNameType == \'sutieid\') { 88 $this->exceDec($sMsg); 89 } else if ($ToUserNameType == \'corpid\') { 90 $this->exceDecInfo($sMsg); 91 } 92 93 } 94 } 95 //如果是从服务商网站发起的授权, 授权完成后是get请求指直接302到服务商网站, 96 else if ($_SERVER[\'REQUEST_METHOD\'] === \'GET\' && isset($get[\'auth_code\'])) { 97 98 } 99 //其他请求, 不处理 100 else { 101 LogException::write("otherrequest\n\n"); 102 } 103 } 104 105 106 /** 107 * 解析内容, 第三方企业号专用 108 */ 109 public function exceDec($sMsg, $type = \'online\') 110 { 111 $xml = new DOMDocument(); 112 $xml->loadXML($sMsg); 113 $suite_id = $xml->getElementsByTagName(\'SuiteId\')->item(0)->nodeValue; 114 $info_type = $xml->getElementsByTagName(\'InfoType\')->item(0)->nodeValue; //echo $info_type;exit; 115 $echoStr = \'success\';//注意这里的success, 微信默认会在5分钟内(如果你没有正确的响应)给你推送三次, 116 //所谓的正确响应就是返回一个success字符串 117 switch ($info_type) { 118 case \'suite_ticket\'://推送suite_ticket协议每十分钟微信推送一次 119 $suite_ticket = $xml->getElementsByTagName(\'SuiteTicket\')->item(0)->nodeValue; 120 //剩下的就是你自己的业务看看要存到什么地方, 121 break; 122 case \'change_auth\'://变更授权的通知 需要调用 获取企业号的授权信息, 更改企业号授权信息 123 124 break; 125 case \'cancel_auth\'://取消授权的通知 -- 特指套件取消授权 126 127 break; 128 case \'create_auth\'://授权成功推送auth_code事件 129 130 break; 131 default: 132 break; 133 } 134 echo $echoStr; 135 } 136 137 /** 138 * 在微信推送取消授权和变更授权操作时, 重新获得授权信息, 并更新授权应用, 会在exceDec方法中调用 139 */ 140 private function doChangeCancelAuth($suite_id, $auth_corp_id) 141 { 142 143 } 144 145 /** 146 * 解析事件推送和普通消息推送 147 * @param String(xml) $sMsg 148 */ 149 public function exceDecInfo($sMsg) 150 { 151 152 } 153 154 155 }
到了这一步完成, 后面, 跟着企业授权应用的流程走, 用哪个接口就对接哪个接口即可, 主要是处理一些业务上的需求, 取消变更套件的定义, 什么时候推送授权成功的信息, 还有就是线上自助授权方式微信会直接跳到服务商主页, ,参数里面有一个auth_code
想要做服务商辅助授权的方式, 你的应用必须要上线才行, 否则只能在你应用的管理后台最后我上一个我自己的比较完整的controller, 使用tp3.2写的,
1 <?php 2 3 namespace Wx\Controller; 4 5 use Common\Common\LogException; 6 use Common\Common\WxApi; 7 use Common\Common\Utils\AES256; 8 use Common\Common\Service\AppService; 9 10 class ApiController extends BaseController 11 { 12 13 private $encoding_aes_key; 14 private $token; 15 private $corp_id; 16 private $suite_id; //所有应用套件的应用id , 数据类型是array 17 private $wxcpt; 18 19 public function _initialize() 20 { 21 header("Content-Type:text/html; charset=utf-8"); 22 $this->corp_id = \'你的corpid\'; 23 $this->suite_id = array( 24 \'suiteid\'=>array(\'suiteid\'=>,\'suite_token\'=>,\'suite_encoding_aes_key\'=>,), 25 \'suiteid\'=>array(\'suiteid\'=>,\'suite_token\'=>,\'suite_encoding_aes_key\'=>,), 26 );//我是从数据库取的 ,这里只是一个示例 27 } 28 29 public function index() 30 { 31 32 $get = I("get."); 33 $msg_sig = $get[\'msg_signature\']; 34 $time_stamp = $get[\'timestamp\']; 35 $nonce = $get[\'nonce\']; 36 $corpid = $get[\'corpid\']; 37 38 if ($_SERVER[\'REQUEST_METHOD\'] === \'GET\' && isset($get[\'echostr\'])) { 39 40 $sVerifyEchoStr = $get[\'echostr\']; //单独获取校验echostr 41 $sEchoStr = ""; 42 foreach($this->suite_id as $k=>$v){ 43 $this->encoding_aes_key = $v[\'suite_encoding_aes_key\']; 44 $this->token = $v[\'suite_token\']; 45 $this->wxcpt = new \WXBizMsgCrypt($this->token, $this->encoding_aes_key, $this->corp_id); 46 $err_code = $this->wxcpt->VerifyURL($msg_sig, $time_stamp, $nonce, $sVerifyEchoStr, $sEchoStr); 47 48 if ($err_code == 0) { 49 echo $sEchoStr; 50 exit; 51 } 52 } 53 54 } 55 else if ($_SERVER[\'REQUEST_METHOD\'] === \'POST\') { 56 // post请求的密文数据 57 // $sReqData = HttpUtils.PostData(); 58 $sReqData = file_get_contents("php://input"); //必须通过输入流方式获取post数据, 数据头为{"Content-Type":"application/xml"} 59 $xml = new \DOMDocument(); 60 $xml->loadXML($sReqData); 61 $ToUserName = $xml->getElementsByTagName(\'ToUserName\')->item(0)->nodeValue; 62 $ToUserNameType = \'\'; 63 $sassInfo = array(); 64 65 foreach($this->suite_id as $k => $v){ 66 if($v[\'suite_id\'] == $ToUserName){ 67 $sassInfo = $v; 68 $ToUserNameType = \'sutieid\'; 69 break; 70 } 71 } 72 //如果以上for循环不能得到套件结果, 说明不是回调接口来的请求, ToUserName对应的肯定是一个普通企业的corpid, 这时还要通过Agentid参数来获得 73 //到底是哪个应用来的请求数据 74 if(empty($sassInfo)){ 75 //通过corpid和Agentid反推来得到到底是哪个套件, 因为实例化解密类的时候, 需要token和encoding_aes_key 76 $ToUserNameType = \'corpid\'; 77 } 78 79 $this->wxcpt = new \WXBizMsgCrypt($sassInfo[\'suite_token\'], $sassInfo[\'suite_encoding_aes_key\'], $ToUserName); 80 $err_code = -1; 81 $sMsg = ""; // 解析之后的明文 82 $err_code = $this->wxcpt->DecryptMsg($msg_sig, $time_stamp, $nonce, $sReqData, $sMsg);//var_dump($get,$err_code,$sMsg);//exit; 83 if($err_code == 0){ 84 if ($ToUserNameType == \'sutieid\') { 85 $this->exceDec($sMsg); 86 } else if ($ToUserNameType == \'corpid\') { 87 $this->exceDecInfo($sMsg); 88 } 89 90 } 91 92 } 93 //这种情况是在服务商辅助授权方式授权的应用, 微信没有回调, 只会在回调url里面有auth_code这个参数, 也就是临时授权码, 这样就相当于模拟了一个请求, 交给相同的方法来处理授权 94 else if ($_SERVER[\'REQUEST_METHOD\'] === \'GET\' && isset($get[\'auth_code\'])) { 95 $auth_code = $get[\'auth_code\']; 96 $state = $get[\'state\'];//var_dump($state); 97 $suite_id = \'\';//解密$state获得suiteid, 我在授权请求的state参数, 把suiteid加密了 98 $time = time(); 99 $sMsg = <<<EOD 100 <xml> 101 <SuiteId><![CDATA[$suite_id]]></SuiteId> 102 <AuthCode><![CDATA[$auth_code]]></AuthCode> 103 <InfoType><![CDATA[create_auth]]></InfoType> 104 <TimeStamp>$time</TimeStamp> 105 </xml> 106 EOD; 107 108 $this->exceDec($sMsg, \'server\'); 109 } 110 else { 111 LogException::write("otherrequest\n\n"); 112 } 113 } 114 115 116 /** 117 * 解析内容, 第三方企业号专用 118 */ 119 public function exceDec($sMsg, $type = \'online\') 120 { 121 $xml = new \DOMDocument(); 122 $xml->loadXML($sMsg); 123 $suite_id = $xml->getElementsByTagName(\'SuiteId\')->item(0)->nodeValue; 124 $info_type = $xml->getElementsByTagName(\'InfoType\')->item(0)->nodeValue; 125 $echoStr = \'success\'; 126 $global_options = get_option(\'ft_global_options\'); 127 switch ($info_type) { 128 case \'suite_ticket\'://推送suite_ticket协议每十分钟微信推送一次 129 $suite_ticket = $xml->getElementsByTagName(\'SuiteTicket\')->item(0)->nodeValue; 130 131 if (!empty($suite_ticket)) {//echo $suite_ticket;exit; 132 //存suite_ticket 133 } 134 else { 135 //错误信息 136 } 137 138 break; 139 case \'change_auth\'://变更授权的通知 需要调用 获取企业号的授权信息, 更改企业号授权信息 140 $auth_corp_id = $xml->getElementsByTagName(\'AuthCorpId\')->item(0)->nodeValue;//普通企业的corpid 141 //业务需求 142 break; 143 case \'cancel_auth\'://取消授权的通知 -- 特指套件取消授权 144 $auth_corp_id = $xml->getElementsByTagName(\'AuthCorpId\')->item(0)->nodeValue;//普通企业的corpid 145 //自己的业务需求 146 break; 147 case \'create_auth\'://授权成功推送auth_code事件 148 //获取AuthCode 149 $auth_code = $xml->getElementsByTagName(\'AuthCode\')->item(0)->nodeValue; 150 if (!empty($auth_code)) { 151 152 //服务商辅助授权方式安装应用 153 if (\'online\' !== $type && \'server\' === $type) { 154 155 } 156 //线上自助授权安装应用 157 else if (\'online\' == $type) { 158 159 } 160 161 162 163 } 164 break; 165 default: 166 break; 167 } 168 echo $echoStr; 169 } 170 171 172 /** 173 * 解析事件推送和普通消息推送 174 * @param String(xml) $sMsg 175 */ 176 public function exceDecInfo($sMsg) 177 { 178 $xml = new \DOMDocument(); 179 $xml->loadXML($sMsg); 180 $toUserName = $corpid = $xml->getElementsByTagName(\'ToUserName\')->item(0)->nodeValue; 181 $fromUserName = $userid = $xml->getElementsByTagName(\'FromUserName\')->item(0)->nodeValue; 182 $msgType = $xml->getElementsByTagName(\'MsgType\')->item(0)->nodeValue; 183 $agentID = $xml->getElementsByTagName(\'AgentID\')->item(0)->nodeValue; 184 185 //TODO 186 $data = array( 187 \'corpid\'=>$corpid, 188 \'userid\'=>$userid, 189 \'msgType\'=>$msgType, 190 \'agentid\'=>$agentID, 191 ); 192 193 } 194 195 }