diff --git a/MIT-LICENSE.txt b/MIT-LICENSE.txt index 0624076..08a8c8a 100644 --- a/MIT-LICENSE.txt +++ b/MIT-LICENSE.txt @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2014-2017 Anyon +Copyright (c) 2014-2017 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index fce95d2..4a4c64f 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,11 @@ -[![Latest Stable Version](https://poser.pugx.org/zoujingli/wechat-php-sdk/v/stable)](https://packagist.org/packages/zoujingli/wechat-php-sdk) -[![Total Downloads](https://poser.pugx.org/zoujingli/wechat-php-sdk/downloads)](https://packagist.org/packages/zoujingli/wechat-php-sdk) -[![Latest Unstable Version](https://poser.pugx.org/zoujingli/wechat-php-sdk/v/unstable)](https://packagist.org/packages/zoujingli/wechat-php-sdk) -[![License](https://poser.pugx.org/zoujingli/wechat-php-sdk/license)](https://packagist.org/packages/zoujingli/wechat-php-sdk) - 此`SDK`运行最底要求`PHP`版本`5.3`, 建议在`PHP7`上运行以获取最佳性能。 微信的部分接口需要缓存数据在本地,因此对目录需要有写权限。 我们鼓励大家使用`composer`来管理您的第三方库,方便后期更新操作(尤其是接口类)。 -近期`access_token`经常无故失效,`SDK`已加入失败状态检测,自动重新获取`access_token`并返回结果. - 此`SDK`已历经数个线上项目验证与考验,可靠性与稳定性极高,欢迎`fork`或`star`此项目。 -# 新微信开发工具推荐 -WeChatDeveloper:https://github.com/zoujingli/WeChatDeveloper - -**微信SDK开发帮助及交流** --- -* **在做微信开发前,必需先阅读微信官方文档,此SDK也是基于之上进行的封装。** - -* **文档链接地址**:http://www.kancloud.cn/zoujingli/wechat-php-sdk - -* **Think.Admin**:https://github.com/zoujingli/Think.Admin - -* **开发交流QQ群:513350915(新)** - -**若对您有帮助,可以赞助并支持下作者哦,谢谢!** --- -![](http://plugs.ctolog.com/pay.png) **官方接口文档链接** @@ -39,13 +16,7 @@ WeChatDeveloper:https://github.com/zoujingli/WeChatDeveloper * 微信开放平台:https://open.weixin.qq.com/ * 微信支付接入文档:https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN * 微信商户平台:https://pay.weixin.qq.com - -**微信`SDK`项目源文件托管** --- -* SDK 为开源项目,你可以把它用于任何地址,并不受任何约束,欢迎`fork`项目。 -* 通过 [Github](https://github.com/zoujingli/wechat-php-sdk) 下载 SDK 源代码 -* 通过 [OSChina](http://git.oschina.net/zoujingli/wechat-php-sdk) 下载 SDK 源代码 -* 通过 [Composer](https://getcomposer.org) 包管理工具下载 SDK 源代码 +* 第三方平台接入 : https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489144594_DhNoV&token=&lang= **微信`SDK`封装对接及功能** -- @@ -76,12 +47,13 @@ WeChatDeveloper:https://github.com/zoujingli/WeChatDeveloper * 认证权限:分为订阅号、服务号认证,如前缀服务号则仅认证的服务号有此权限 * 支付权限:仅认证后的服务号可以申请此权限 -**微信开放第三方平台** --- (案例及文档整理中) +**微信开放第三方平台** --- -- -* 公众号授权服务 +* 授权服务 * 公众号推送消息代处理 * 公众号基础业务代处理 * 公众号支付代发起 +* 小程序基础业务代理 **微信`SDK`版权声明** -- diff --git a/Wechat/Loader.php b/Wechat/Loader.php index ae9fc85..24d9d4d 100644 --- a/Wechat/Loader.php +++ b/Wechat/Loader.php @@ -90,6 +90,8 @@ static public function & get_instance($type, $config = array()) static public function & get($type, $config = array()) { $index = md5(strtolower($type) . md5(json_encode(self::$config))); + #不做缓存 + unset(self::$cache[$index]); if (!isset(self::$cache[$index])) { $basicName = 'Wechat' . ucfirst(strtolower($type)); $className = "\\Wechat\\{$basicName}"; diff --git a/Wechat/WechatApplet.php b/Wechat/WechatApplet.php new file mode 100644 index 0000000..5955344 --- /dev/null +++ b/Wechat/WechatApplet.php @@ -0,0 +1,756 @@ +errMsg = '参数错误.(bind/unbind)'; + $this->errCode = ''; + return false; + } + //是否授权 + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + if($action == 'bind'){ + $url = 'https://api.weixin.qq.com/wxa/bind_tester?access_token='.$auth_info['authorizer_access_token']; + }else{ + $url = 'https://api.weixin.qq.com/wxa/unbind_tester?access_token=TOKEN'.$auth_info['authorizer_access_token']; + } + + $data['wechatid'] = $wechatId; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + return $this->returnBool($returnData); + + } + + /** + * 设置小程序业务域名 (仅供第三方代小程序调用) + * @param string $action add添加, delete删除, set覆盖, get获取 + * @param array $webViewDomain request合法域名 + * @return bool | array 以下字段仅在get时返回 {webviewdomain} + */ + public function webViewDomain($action = 'get',$webViewDomain = []){ + if($action != 'get'){ + if(empty($webViewDomain) ){ + $this->errMsg = '小程序业务域名必须'; + $this->errCode = ''; + return false; + } + } + + //是否授权 + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + //组装 + $data['webviewdomain'] = $webViewDomain; + + $url = 'https://api.weixin.qq.com/wxa/modify_domain?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + return $this->returnBool($returnData); + + } + + /** + * 设置小程序服务器域名 + * @param string $action add添加, delete删除, set覆盖, get获取 + * @param array $requestDomain request合法域名 + * @param array $wsRequestDomain socket合法域名 + * @param array $uploadDomain uploadFile合法域名 + * @param array $downloadDomain downloadFile合法域名 + * @return bool | array 以下字段仅在get时返回 {requestdomain,wsrequestdomain,uploaddomain,downloaddomain} + */ + public function wxaDomain($action = 'get',$requestDomain = [],$wsRequestDomain=[],$uploadDomain=[],$downloadDomain=[]){ + #当参数是get时不需要填四个域名字段 + if($action != 'get'){ + if(empty($requestDomain) || empty($wsRequestDomain) || empty($uploadDomain) || empty($downloadDomain)){ + $this->errMsg = '当action参数不是get时需要填四个域名字段'; + $this->errCode = ''; + return false; + } + } + + //是否授权 + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + //组装 + $data['requestdomain'] = $requestDomain; + $data['wsrequestdomain'] = $wsRequestDomain; + $data['uploaddomain'] = $uploadDomain; + $data['downloaddomain'] = $downloadDomain; + + $url = 'https://api.weixin.qq.com/wxa/modify_domain?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + if($returnData['errcode'] == 0){ + if($action == 'get'){ + return $returnData; + }else{ + return true; + } + }else{ + $this->errMsg = isset($returnData['errmsg'])?$returnData['errmsg']:'修改失败'; + $this->errCode =isset($returnData['errcode'])?$returnData['errcode']:''; + return false; + } + + } + + /** + * 为授权的小程序帐号上传小程序代码 + * @param string $template_id 代码库中的代码模版ID + * @param string $ext_json 第三方自定义的配置 + * @param string $user_version 代码版本号,开发者可自定义 + * @param string $user_desc 代码描述,开发者可自定义 + * @return bool + */ + public function commit($template_id,$ext_json,$user_version,$user_desc){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $data['template_id'] = $template_id; + $data['ext_json'] = $ext_json; + $data['user_version'] = $user_version; + $data['user_desc'] = $user_desc; + + $url = 'https://api.weixin.qq.com/wxa/commit?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + return $this->returnBool($returnData); + } + + /** + * 获取体验小程序的体验二维码 + * @param string $path 指定体验版二维码跳转到某个具体页面 可不填 + * @return bool|mixed 返回图片资源 + */ + public function getQrcode($path = ''){ + //鉴权 + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + if($path){ + $suffix = '&path='.$path; + }else{ + $suffix = ''; + } + + $url = 'https://api.weixin.qq.com/wxa/commit?access_token='.$auth_info['authorizer_access_token'].$suffix; + $returnData = Tools::httpGet($url); + + if(json_decode($returnData)){ + + $this->errMsg = isset($returnData['errmsg'])?$returnData['errmsg']:''; + $this->errCode =isset($returnData['errcode'])?$returnData['errcode']:''; + return false; + }else{ + + return $returnData; + } + } + + /** + * 获取授权小程序帐号的可选类目 + * @return bool | array {category_list:[]} + */ + public function getCategory(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + $url = 'https://api.weixin.qq.com/wxa/get_category?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpGet($url)); + return $this->returnResult($returnData); + } + + /** + * 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用) + * @return bool|mixed {page_list:[]} + */ + public function getPage(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + $url = 'https://api.weixin.qq.com/wxa/get_page?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpGet($url)); + return $this->returnResult($returnData); + } + + /** + * 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用) + * @param $item_list + * @return bool|array {item_list:[{address,tag,first_class,second_class,first_id,second_id,title}]} + */ + public function submitAudit($item_list){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + if(!is_array($item_list) || empty($item_list)){ + $this->errMsg = '提交审核项的一个列表'; + $this->errCode =''; + return false; + } + + $data['item_list'] = $item_list; + $url = 'https://api.weixin.qq.com/wxa/submit_audit?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + return $this->returnResult($returnData); + } + + /** + * 回调 获取审核结果 + * @return array|bool 消息内容 + */ + public function revAuditResult(){ + $receive = new WechatReceive(array( + 'appid' => $this->component_appid, + 'appsecret' => $this->component_appsecret, + 'encodingaeskey' => $this->component_encodingaeskey, + 'token' => $this->component_token, + 'cachepath' => Cache::$cachepath + )); + # 会话内容解密状态判断 + if (false === $receive->valid()) { + $this->errCode = $receive->errCode; + $this->errMsg = $receive->errMsg; + Tools::log("获取小程序审核结果失败. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}"); + return false; + } + $data = $receive->getRev()->getRevData(); + if ($data['Event'] === 'weapp_audit_success' || $data['Event'] === 'weapp_audit_success' ) { + return $data; + }else{ + + return false; + } + + } + + /** + * 查询某个指定版本的审核状态(仅供第三方代小程序调用) + * @param string $audit_id 提交审核时获得的审核id + * @return bool | array {status:0审核成功|1 审核被拒(有返回reason) |2 审核中 , reason} + */ + public function getAuditStatus($audit_id){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $data['auditid'] = $audit_id; + $url = 'https://api.weixin.qq.com/wxa/commit?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + return $this->returnResult($returnData); + } + + /** + * 查询最新一次提交的审核状态 + * @return bool | array {auditid ,status:0审核成功|1 审核被拒(有返回reason) |2 审核中 , reason} + */ + public function getLastAuditResult(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + $url = 'https://api.weixin.qq.com/wxa/get_page?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpGet($url)); + return $this->returnResult($returnData); + + } + + /** + * 发布已通过审核的小程序(仅供第三方代小程序调用) + * @return bool + */ + public function release(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/wxa/release?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode([]))); + return $this->returnBool($returnData); + } + + /** + * 修改小程序线上代码的可见状态(仅供第三方代小程序调用) + * @param string $action 设置可访问状态,发布后默认可访问,close为不可见,open为可见 + * @return bool + */ + public function changeVisitstatus($action){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + if($action != 'close' || $action != 'open'){ + $this->errMsg = '参数错误: 仅为close/open'; + $this->errCode = ''; + return false; + } + + + $url = 'https://api.weixin.qq.com/wxa/change_visitstatus?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode([]))); + return $this->returnBool($returnData); + } + + /** + * 小程序版本回退(仅供第三方代小程序调用) + * @return bool + */ + public function revertCodeRelease(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + $url = 'https://api.weixin.qq.com/wxa/revertcoderelease?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpGet($url)); + return $this->returnBool($returnData); + } + + /** + * 查询当前设置的最低基础库版本及各版本用户占比 + * @return bool | array { now_version ,uv_info} + */ + public function getSupportVersion(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + + $url = 'https://api.weixin.qq.com/wxa/change_visitstatus?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode([]))); + return $this->returnResult($returnData); + } + + /** + * 设置最低基础库版本(仅供第三方代小程序调用) + * @param string $version 版本号 + * @return bool + */ + public function setSupportVersion($version){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion?access_token='.$auth_info['authorizer_access_token']; + $data['version'] = $version; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnBool($returnData); + } + + /** + * 增加或修改二维码规则 + * @param string $prefix + * @param string $permit_sub_rule #https://mp.weixin.qq.com/debug/wxadoc/introduction/qrcode.html#前缀占用规则 + * @param string $path + * @param string $open_version + * @param array $debug_url + * @param string $is_edit + * @return bool + */ + public function editOrAddQrcodeRule($prefix,$permit_sub_rule,$path,$open_version,$debug_url,$is_edit){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpadd?access_token='.$auth_info['authorizer_access_token']; + + $data['prefix'] = $prefix; + $data['permit_sub_rule'] = $permit_sub_rule; + $data['path'] = $path; + $data['open_version'] = $open_version; + $data['debug_url'] = $debug_url; + $data['is_edit'] = $is_edit; + + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnResult($returnData); + } + + /** + * 获取已设置的二维码规则 + * @return bool |array 规则列表 {rule_list:[],list_size,qrcodejump_open,qrcodejump_pub_quota} + */ + public function getQrcodeRule(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpget?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode([]))); + + return $this->returnResult($returnData); + } + + /** + * 获取校验文件名称及内容 + * @return bool |array {file_name,file_content} + */ + public function qrcodeValidFile(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpdownload?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode([]))); + + return $this->returnResult($returnData); + } + + /** + * 发布已设置的二维码规则 + * @param string $prefix 二维码规则 (获取已设置二维码规则结果获得) + * @return bool + */ + public function releaseQrcodeRule($prefix){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpdownload?access_token='.$auth_info['authorizer_access_token']; + + $data['prefix'] = $prefix; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnBool($returnData); + } + + /** + * 小程序审核撤回 + * @return bool + * !单个帐号每天审核撤回次数最多不超过1次,一个月不超过10次。 + */ + public function revokeAudit(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/wxa/undocodeaudit?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode([]))); + + return $this->returnBool($returnData); + } + + /** + * 分阶段发布接口 + * @param int $gray_percentage 灰度的百分比,1到100的整数 + * @return bool + */ + public function grayRelease($gray_percentage){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/wxa/grayrelease?ccess_token='.$auth_info['authorizer_access_token']; + $data['gray_percentage'] = $gray_percentage; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnBool($returnData); + } + + /** + * 取消分阶段发布 + * @return bool + */ + public function revertGrayRelease(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/wxa/revertgrayrelease?access_token='.$auth_info['authorizer_access_token']; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode([]))); + + return $this->returnBool($returnData); + } + + /** + * 获取草稿箱内的所有临时代码草稿 + * @return bool |array {create_time,user_version,user_desc,draft_id} + */ + public function getTemplateDrafList(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + $url = 'https://api.weixin.qq.com/wxa/gettemplatedraftlist?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpGet($url)); + return $this->returnResult($returnData); + } + + /** + * 获取代码模版库中的所有小程序代码模版 + * @return bool |array {template_list:[{create_time,user_version,user_desc,template_id}]} + */ + public function getTemplateList(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + $url = 'https://api.weixin.qq.com/wxa/gettemplatelist?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpGet($url)); + return $this->returnBool($returnData); + } + + /** + * 将草稿箱的草稿选为小程序代码模版 + * @param int $draft_id 草稿id + * @return bool + */ + public function addToTemplate($draft_id){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/wxa/addtotemplate?access_token='.$auth_info['authorizer_access_token']; + $data['draft_id'] = $draft_id; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnBool($returnData); + } + + /** + * 删除指定小程序代码模版 + * @param int $template_id + * @return bool + */ + public function delTemplate($template_id){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/wxa/deletetemplate?access_token='.$auth_info['authorizer_access_token']; + $data['template_id'] = $template_id; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnBool($returnData); + } + + /** + * 获取小程序模板库标题列表 + * @param int $offset offset表示从offset开始 + * @param int $count 拉取count条记录 + * @return bool |array {list:[{id,title}]} + */ + public function msgTemplateList($offset,$count){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list?access_token='.$auth_info['authorizer_access_token']; + $data['offset'] = $offset; + $data['count'] = $count; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnResult($returnData); + } + + /** + * 通过消息模板id获取模板库某个模板标题下关键词库 + * @param int $msg_templet_id 消息模板id + * @return bool | array {id,title,keyword_list:[{keyword_id,name,example}]} + */ + public function getMsgTemplate($msg_templet_id){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token='.$auth_info['authorizer_access_token']; + $data['id'] = $msg_templet_id; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnResult($returnData); + } + + /** + * 组合模板并添加至帐号下的个人模板库 + * @param int $template_id 消息模板id + * @param array $keyword_ids 关键词id数组 (通过消息模板详情接口获取 + * @return bool | array {template_id} + */ + public function addMsgTemplate($template_id,$keyword_ids){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/add?access_token='.$auth_info['authorizer_access_token']; + $data['id'] = $template_id; + $data['keyword_id_list'] = $keyword_ids; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnResult($returnData); + } + + /** + * 获取帐号下已存在的模板列表 + * @param int $offset offset表示从offset开始 + * @param int $count 拉取count条记录 + * @return bool |array {list:[{template_id,title,content,example}]} + * + */ + public function getMyMsgTemplateList($offset,$count){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token='.$auth_info['authorizer_access_token']; + $data['offset'] = $offset; + $data['count'] = $count; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnResult($returnData); + } + + /** + * 删除帐号下的某个模板 + * @param int $template_id 消息模板id + * @return bool + */ + public function delMsgTemplate($template_id){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/del?access_token='.$auth_info['authorizer_access_token']; + $data['template_id'] = $template_id; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnResult($returnData); + } + + /** + * 设置小程序隐私设置(是否可被搜索) + * @param int $status 1表示不可搜索,0表示可搜索 + * @return bool + */ + public function setSearchStatus($status){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + + $url = 'https://api.weixin.qq.com/wxa/changewxasearchstatus?access_token='.$auth_info['authorizer_access_token']; + $data['status'] = $status; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + return $this->returnBool($returnData); + } + + /** + * 查询小程序当前隐私设置(是否可被搜索) + * @return bool |array {status} + */ + public function getSearchStatus(){ + $auth_info = $this->getAuthTokenCache(); + if(!$auth_info){ + return false; + } + $url = 'https://api.weixin.qq.com/wxa/getwxasearchstatus?access_token='.$auth_info['authorizer_access_token']; + + $returnData = $this->parseJson(Tools::httpGet($url)); + return $this->returnResult($returnData); + + } + + /** + * 返回bool值 + * @param array $returnData 微信返回数据 + * @return bool + */ + private function returnBool($returnData){ + if($returnData['errcode'] != 0){ + + $this->errMsg = $returnData['errmsg']; + $this->errCode = $returnData['errcode'] ; + return false; + }else{ + + return true; + } + } + + /** + * 返回数组 + * @param array $returnData 微信返回数据 + * @return bool |array + */ + private function returnResult($returnData){ + if($returnData['errcode'] != 0){ + + $this->errMsg = $returnData['errmsg']; + $this->errCode = $returnData['errcode'] ; + return false; + }else{ + + return $returnData; + } + } + + +} \ No newline at end of file diff --git a/Wechat/WechatPay.php b/Wechat/WechatPay.php index 257be09..baed930 100644 --- a/Wechat/WechatPay.php +++ b/Wechat/WechatPay.php @@ -203,8 +203,8 @@ public function createMicroPay($auth_code, $out_trade_no, $total_fee, $body, $go } /** - * 支付通知验证处理 - * @return bool|array + * 获取支付通知 + * @return bool|array 支付通知 */ public function getNotify() { @@ -221,6 +221,15 @@ public function getNotify() $this->errMsg = 'Payment notification signature is missing.'; return false; } + return $notifyInfo; + } + + /** + * 验证支付通知 + * @param array $notifyInfo 获取支付通知接口返回 + * @return bool | array + */ + function checkNotifySign($notifyInfo){ $data = $notifyInfo; unset($data['sign']); if ($notifyInfo['sign'] !== Tools::getPaySign($data, $this->partnerKey)) { @@ -235,7 +244,6 @@ public function getNotify() return $notifyInfo; } - /** * 支付XML统一回复 * @param array $data 需要回复的XML内容数组 diff --git a/Wechat/WechatService.php b/Wechat/WechatService.php index f9b8541..48e44ee 100644 --- a/Wechat/WechatService.php +++ b/Wechat/WechatService.php @@ -42,28 +42,33 @@ class WechatService const GET_AUTHORIZER_OPTION_URL = '/api_get_authorizer_option'; // 设置授权方的选项信息 const SET_AUTHORIZER_OPTION_URL = '/api_set_authorizer_option'; + // 未授权 + const UNAUTH = 40001; - // 微信后台推送的ticket 每十分钟更新一次 + // token缓存前缀 + const AUTH_TOKEN_TAG = 'auth_token_'; + + // 错误码 public $errCode; - // 服务appid + // 错误信息 public $errMsg; - // 服务appsecret + // 推送ticket protected $component_verify_ticket; - // 公众号消息校验Token + // 第三方平台appid protected $component_appid; - // 公众号消息加解密Key + // 第三方平台appsecret protected $component_appsecret; // 服务令牌 protected $component_token; - // 授权方appid + // 第三方平台组件加密密钥 protected $component_encodingaeskey; - // 授权方令牌 + // 第三方调用接口凭证 protected $component_access_token; - // 刷新令牌 + // 授权方appid protected $authorizer_appid; - // JSON数据 + // 预授权码 protected $pre_auth_code; - // 错误消息 + // 返回数据 protected $data; /** @@ -78,10 +83,12 @@ public function __construct($options = array()) $this->component_appsecret = !empty($options['component_appsecret']) ? $options['component_appsecret'] : ''; $this->component_token = !empty($options['component_token']) ? $options['component_token'] : ''; $this->component_appid = !empty($options['component_appid']) ? $options['component_appid'] : ''; + $this->authorizer_appid = !empty($options['authorizer_appid']) ? $options['authorizer_appid'] : ''; + } /** - * 接收公众平台推送的 Ticket + * 接收推送的 Ticket * @return bool|array */ public function getComonentTicket() @@ -110,14 +117,14 @@ public function getComonentTicket() } /** - * 获取(刷新)授权公众号的令牌 - * @注意1. 授权公众号访问access token2小时有效 + * 获取(刷新)授权的令牌 + * @注意1. 授权访问access token2小时有效 * @注意2. 一定保存好新的刷新令牌 * @param string $authorizer_appid 授权方APPID * @param string $authorizer_refresh_token 授权方刷新令牌 * @return bool|string */ - public function refreshAccessToken($authorizer_appid, $authorizer_refresh_token) + private function refreshAccessToken($authorizer_appid, $authorizer_refresh_token) { empty($this->component_access_token) && $this->getComponentAccessToken(); if (empty($this->component_access_token)) { @@ -165,7 +172,7 @@ public function getComponentAccessToken() * @param string|null $field * @return bool|array */ - private function _decode($result, $field = null) + protected function _decode($result, $field = null) { $this->data = json_decode($result, true); if (!empty($this->data['errcode'])) { @@ -184,7 +191,7 @@ private function _decode($result, $field = null) } /** - * 获取公众号的授权信息 + * 获取授权信息 * * @param string $authorization_code * @return bool|array @@ -205,6 +212,16 @@ public function getAuthorizationInfo($authorization_code) Tools::log("Get getAuthorizationInfo Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}"); return false; } + Tools::log(json_encode($authorization_info)); + + //保存授权方信息 + $this->setAuthTokenCache( + $authorization_info['authorizer_appid'], + $authorization_info['authorizer_access_token'], + $authorization_info['authorizer_refresh_token'], + $authorization_info['expires_in'] + ); + $authorization_info['func_info'] = $this->_parseFuncInfo($authorization_info['func_info']); return $authorization_info; } @@ -214,7 +231,7 @@ public function getAuthorizationInfo($authorization_code) * @param array $func_info * @return string */ - private function _parseFuncInfo($func_info) + protected function _parseFuncInfo($func_info) { $authorization_list = array(); foreach ($func_info as $func) { @@ -318,7 +335,6 @@ public function getAuthRedirect($redirect_uri) /** * 获取预授权码 - * * @return bool|string */ public function getPreauthCode() @@ -378,9 +394,9 @@ public function getOauthAccessToken($appid) /** * 解析JSON数据 * @param string $result - * @return bool + * @return bool | array */ - private function parseJson($result) + protected function parseJson($result) { $json = json_decode($result, true); if (empty($json) || !empty($json['errcode'])) { @@ -405,4 +421,70 @@ public function getOauthUserInfo($openid, $oauthAccessToken) } + + /** + * 保存授权方信息到缓存 + * @param string $authorizer_appid + * @param string $authorizer_access_token + * @param string $authorizer_refresh_token + * @param int $expired_in + */ + protected function setAuthTokenCache($authorizer_appid,$authorizer_access_token,$authorizer_refresh_token,$expired_in){ + $cacheKey = self::AUTH_TOKEN_TAG.md5($authorizer_appid); + $cahce_data = [ + 'authorizer_access_token' => $authorizer_access_token, + 'authorizer_refresh_token' => $authorizer_refresh_token, + 'expired_time' => time()+$expired_in, #提前10分钟刷新 + ]; + //todo::加入到刷新token队列? + Tools::setCache($cacheKey,$cahce_data, $expired_in); + } + + /** + * 获取授权方RefreshToken,AccessToken (获取失败则需重新授权) | 做验证授权状态用 + * @return bool|array {authorizer_access_token,authorizer_refresh_token} + */ + protected function getAuthTokenCache(){ + + $cacheKey = self::AUTH_TOKEN_TAG.md5($this->authorizer_appid); + + $cacheData = Tools::getCache($cacheKey); + if($cacheData){ + //是否即将过期 + if($cacheData['expired_time'] + 600 < time()){ + + $data['component_appid'] = $this->component_appid; + $data['authorizer_appid'] = $this->authorizer_appid; + $data['authorizer_refresh_token'] = $cacheData['authorizer_refresh_token']; + $url = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token={$this->component_access_token}"; + $returnData = $this->parseJson(Tools::httpPost($url, Tools::json_encode($data))); + + if(isset($returnData['authorizer_access_token'])){ + + $this->setAuthTokenCache( + $this->authorizer_appid, + $returnData['authorizer_access_token'], + $returnData['authorizer_refresh_token'], + $returnData['expires_in'] + ); + }else{ + + Tools::log($this->authorizer_appid."刷新token失败."); + } + } + + return $cacheData; + }else{ + + $this->errCode = self::UNAUTH; + $this->errMsg = '获取令牌失败.请重新授权'; + Tools::log("获取令牌失败.请重新授权"); + return false; + } + } + + + + + } diff --git a/auth_code.php b/auth_code.php new file mode 100644 index 0000000..dd11523 --- /dev/null +++ b/auth_code.php @@ -0,0 +1,34 @@ +'component_encodingaeskey', + 'component_verify_ticket'=>'', + 'component_appsecret'=>'component_appsecret', + 'component_token'=>'component_token', + 'component_appid'=>'component_appid', + 'authorizer_appid' => 'authorizer_appid', + ]); + #用户授权后跳转至此. + + #保存用户授权token + $wxa->getAuthorizationInfo($_GET['auth_code']); + $category_rst = $wxa->getCategory(); + var_dump($category_rst); + $wxa->getLastAuditResult(); + $wxa->getPage(); + $wxa->getSearchStatus(); + $wxa->getTemplateList(); + +}else{ + echo 'do nothing'; +} \ No newline at end of file diff --git a/composer.json b/composer.json index b3f9dfd..67b5e5f 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { - "type": "project", - "name": "zoujingli/wechat-php-sdk", - "homepage": "http://www.kancloud.cn/zoujingli/wechat-php-sdk", + "type": "composer-plugin", + "name": "pilipala/wechat-php-sdk", + "homepage": "https://github.com/cyc1994ya/wechat-php-sdk", "description": "WeChat development of SDK", "license": "MIT", "keywords": [ diff --git a/index.php b/index.php new file mode 100644 index 0000000..d742eeb --- /dev/null +++ b/index.php @@ -0,0 +1,43 @@ +'component_encodingaeskey', + 'component_verify_ticket'=>'', + 'component_appsecret'=>'component_appsecret', + 'component_token'=>'component_token', + 'component_appid'=>'component_appid', + 'authorizer_appid' => 'authorizer_appid', + ]); + $redirect_url = $wxa->getAuthRedirect('https://ceshi.xinzhibang168.com/open/auth_code.php'); + + $token = $wxa->getComponentAccessToken(); + if(!$token){ + echo $wxa->errCode.'.'.$wxa->errMsg; + exit('failt to get component access token!'); + } + + $pre_auth_code = $wxa->getPreauthCode(); + if(!$pre_auth_code){ + echo $wxa->errCode.'.'.$wxa->errMsg; + exit('failt to get component access token!'); + } + + + + + + echo ' + + + 这里! + + +' + + ?> + diff --git a/rev.php b/rev.php new file mode 100644 index 0000000..26b5e62 --- /dev/null +++ b/rev.php @@ -0,0 +1,25 @@ +'component_encodingaeskey', + 'component_verify_ticket'=>'', + 'component_appsecret'=>'component_appsecret', + 'component_token'=>'component_token', + 'component_appid'=>'component_appid', + 'authorizer_appid' => 'authorizer_appid', +]); +$getTicketRst = $wxa->getComonentTicket(); +if($getTicketRst){ + echo 'SUCCESS'; + exit(); +} +var_dump($getTicketRst); +echo PHP_EOL; +$getAuditRst = $wxa->revAuditResult(); +var_dump($getAuditRst);