Blogger Information
Blog 143
fans 1
comment 0
visits 440067
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
ThinkPHP5 微信接口对接公共类
弘德誉曦的博客
Original
550 people have browsed it
  1. <?php
  2. // .-----------------------------------------------------------------------------------
  3. // | Software: [wechat framework]
  4. // | Version: 2017.7
  5. // | Site:
  6. // |-----------------------------------------------------------------------------------
  7. // | Author: bug <3164145970@qq.com>
  8. // | Copyright (c) 2017, . All Rights Reserved.
  9. // |-----------------------------------------------------------------------------------
  10. /**
  11. * 基于thinkphp5的微信自定义接口开发
  12. * @package wechat
  13. * @author bug <3164145970@qq.com>
  14. * @createtime 2017-07-26 10:48:30
  15. * @description
  16. */
  17. // |-----------------------------------------------------------------------------------
  18. namespace util;
  19. use think\Exception;
  20. /**
  21. * 微信公共类文件
  22. * @package util
  23. * @author bug <3164145970@qq.com>
  24. * @createtime 2017-07-26 11:10:14
  25. *
  26. */
  27. class WeChat
  28. {
  29. /**********************基础配置 开始********/
  30. /**
  31. * 微信公众号AppId
  32. * @var string
  33. */
  34. private $appid;
  35. /**
  36. * 微信公众号AppSecret
  37. * @var string
  38. */
  39. private $appsecret;
  40. /**
  41. * 微信公众号验证服务器token
  42. * @var string
  43. */
  44. private $token;
  45. /**
  46. * 微信公众号EncodingAESKey
  47. * @var string
  48. */
  49. private $encoding_aeskey;
  50. /**
  51. * 微信公众号商户号
  52. * @var string
  53. */
  54. private $mch_id;
  55. /**
  56. * 微信公众号商户支付密钥
  57. * @var string
  58. */
  59. private $key;
  60. //=======【证书路径设置】=====================================
  61. /**
  62. * TODO:设置商户证书路径
  63. * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
  64. * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
  65. * @var path
  66. */
  67. const SSLCERT_PATH = "\cert\apiclient_cert.pem";
  68. const SSLKEY_PATH = "\cert\apiclient_key.pem";
  69. //=======【curl代理设置】===================================
  70. /**
  71. * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
  72. * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
  73. * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
  74. * @var unknown_type
  75. */
  76. const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";
  77. const CURL_PROXY_PORT = 0;//8080;
  78. //=======【上报信息配置】===================================
  79. /**
  80. * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】,
  81. * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少
  82. * 开启错误上报。
  83. * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报
  84. * @var int
  85. */
  86. const REPORT_LEVENL = 1;
  87. /**
  88. * 微信公共类构造方法
  89. * @author bug <3164145970@qq.com>
  90. * @createtime 2017-07-26 11:10:14
  91. * @param string $appid 微信公众号AppId
  92. * @param string $appsecret 微信公众号AppSecret
  93. * @param string $token 微信公众号验证服务器token
  94. * @param string $encoding_aeskey 微信公众号EncodingAESKey
  95. * @param string $mch_id 微信公众号商户号
  96. * @param string $key 微信公众号商户支付密钥
  97. */
  98. public function __construct(){
  99. $this->appid = config('crm_config.wechat_appid');//获取配置文件中的微信公众号AppId
  100. $this->appsecret = config('crm_config.wechat_secret');//获取配置文件中的微信公众号AppSecret
  101. $this->token = config('crm_config.token');//获取配置文件中的微信公众号验证服务器token
  102. $this->encoding_aeskey = config('crm_config.encoding_aeskey');//获取配置文件中的微信公众号EncodingAESKey
  103. $this->mch_id = config('crm_config.wechat_mch_id');//获取配置文件中的微信公众号商户号
  104. $this->key = config('crm_config.wechat_key');//获取配置文件中的微信公众号商户支付密钥
  105. }
  106. /**********************基础配置 结束********/
  107. /**********************开始开发 开始********/
  108. /**
  109. * token验证服务器
  110. * @author bug <3164145970@qq.com>
  111. * @createtime 2017-07-26 11:10:14
  112. * @param string $nonce 随机数
  113. * @param string $timestamp 时间戳
  114. * @param string $echostr 随机字符串
  115. * @param string $signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
  116. * @return echostr参数内容或false
  117. */
  118. public function token($nonce,$timestamp,$echostr,$signature){
  119. //参数字典序排序
  120. $array = array();
  121. $array = array($nonce, $timestamp, $this->token);
  122. sort($array);
  123. //验证
  124. $str = sha1( implode( $array ) );//sha1加密
  125. //对比验证处理好的str与signature,若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。
  126. if( $str == $signature && $echostr ){
  127. return $echostr;
  128. }
  129. else{
  130. return false;
  131. }
  132. }
  133. /**
  134. * 通过appid和appsecret获取access_token 或从缓存获取基础支持access_token
  135. * @author bug <3164145970@qq.com>
  136. * @createtime 2017-07-26 11:07:24
  137. * @param type true强制获取access_token,用于本地存储的access_token在微信服务器已过期,但在本地服务器未过期时
  138. * @return string 获取到的凭证
  139. */
  140. private function access_token($type){
  141. // //session开始
  142. // if(!isset($_SESSION)){
  143. // session_start();
  144. // }
  145. // //判断缓存中是否存在access_token,如果存在取出来返回
  146. // if(!$type&&isset($_SESSION['access_token'])&&$_SESSION['access_token']['endtime']>time()){
  147. // $result = array('status'=>1,'data'=>$_SESSION['access_token']['val']);
  148. // return $result;
  149. // }
  150. // //配置请求url,加入appid和appsecret参数
  151. // $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$this->appid.'&secret='.$this->appsecret;
  152. // //获取请求结果,并将请求结果转换成json
  153. // $data = string_json($url);
  154. // if(array_key_exists('errcode', $data)){
  155. // $result = array('status'=>40014,'data'=>$data);
  156. // return $result;
  157. // }
  158. // /**将新获取的access_token缓存到服务器 开始**/
  159. // session_set_cookie_params($data['expires_in']); //设置access_token在服务器session中缓存时间
  160. // $access_token['val'] = $data['access_token'];
  161. // $access_token['endtime'] = time()+$data['expires_in'];
  162. // $_SESSION['access_token']= $access_token;
  163. // /**将新获取的access_token缓存到服务器 结束**/
  164. // //返回结果
  165. // $result = array('status'=>2,'data'=>$data['access_token']);
  166. // return $result;
  167. // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
  168. $datas = json_decode(file_get_contents(dirname(__FILE__)."/json/access_token.json"));
  169. if (!$type && $datas->expire_time > time()) {
  170. $result = array('status'=>1,'data'=>$datas->access_token);
  171. return $result;
  172. }
  173. //配置请求url,加入appid和appsecret参数
  174. // 如果是企业号用以下URL获取access_token
  175. // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
  176. $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$this->appid.'&secret='.$this->appsecret;
  177. //获取请求结果,并将请求结果转换成json
  178. $data = string_json($url);
  179. if(array_key_exists('errcode', $data)){
  180. $result = array('status'=>40014,'data'=>$data);
  181. return $result;
  182. }
  183. //将access_token 写入文件
  184. $datas->expire_time = time()+$data['expires_in'];
  185. $datas->access_token = $data['access_token'];
  186. $fp = fopen(dirname(__FILE__)."/json/access_token.json", "w");
  187. fwrite($fp, json_encode($datas));
  188. fclose($fp);
  189. //返回结果
  190. $result = array('status'=>2,'data'=>$data['access_token']);
  191. return $result;
  192. }
  193. /**
  194. * 接口调用上限清零
  195. * @author bug <3164145970@qq.com>
  196. * @createtime 2017-08-30 13:44:55
  197. * @param post_data 请求数据
  198. * @return json 请求结果
  199. */
  200. public function clear_quota(){
  201. //获取access_token
  202. $access_token= $this->access_token(false);
  203. if($access_token['status']!=1 && $access_token['status']!=2){
  204. return $access_token;
  205. }
  206. $post_data['appid'] = $this->appid;
  207. //配置请求url,加入access_token参数
  208. $url = 'https://api.weixin.qq.com/cgi-bin/clear_quota?access_token='.$access_token['data'];
  209. //将json数组转换成字符串数组
  210. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  211. //获取请求结果,并将请求结果转换成json
  212. $data = json_decode(https_request($url,$post_data),true);
  213. //access_token 过期重新获取并重新回调当前函数
  214. if($data['errcode']==42001 || $data['errcode']==40001){
  215. $access_token = $this->access_token(true);
  216. return $this->clear_quota();
  217. }
  218. //返回结果
  219. if($data['errcode']==0&&$data['errmsg']=='ok'){
  220. $result = array('status'=>1,'data'=>$data);
  221. return $result;
  222. }
  223. $result = array('status'=>40014,'data'=>$data);
  224. return $result;
  225. }
  226. /**
  227. * 获取微信服务器IP地址
  228. * @author bug <3164145970@qq.com>
  229. * @createtime 2017-07-26 13:51:20
  230. * @return json ip_list 微信服务器IP地址
  231. */
  232. public function ip_list(){
  233. //获取access_token
  234. $access_token= $this->access_token(false);
  235. if($access_token['status']!=1 && $access_token['status']!=2){
  236. return $access_token;
  237. }
  238. //配置请求url,加入access_token参数
  239. $url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token='.$access_token['data'];
  240. //获取请求结果,并将请求结果转换成json
  241. $data = string_json($url);
  242. if(array_key_exists('errcode', $data)){
  243. //access_token 过期重新获取并重新回调当前函数
  244. if($data['errcode']==42001 || $data['errcode']==40001){
  245. $access_token = $this->access_token(true);
  246. return $this->ip_list();
  247. }
  248. $result = array('status'=>40014,'data'=>$data);
  249. return $result;
  250. }
  251. //返回结果
  252. $result = array('status'=>1,'data'=>$data);
  253. return $result;
  254. }
  255. /**********************开始开发 结束********/
  256. /**********************自定义菜单 开始********/
  257. /**
  258. * 自定义菜单创建接口
  259. * @author bug <3164145970@qq.com>
  260. * @createtime 2017-07-26 14:24:40
  261. * @param post_data 请求数据
  262. * @return json 请求结果
  263. */
  264. public function create_menu($post_data){
  265. //获取access_token
  266. $access_token= $this->access_token(false);
  267. if($access_token['status']!=1 && $access_token['status']!=2){
  268. return $access_token;
  269. }
  270. //配置请求url,加入access_token参数
  271. $url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token='.$access_token['data'];
  272. //将json数组转换成字符串数组
  273. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  274. //获取请求结果,并将请求结果转换成json
  275. $data = json_decode(https_request($url,$post_data),true);
  276. //access_token 过期重新获取并重新回调当前函数
  277. if($data['errcode']==42001 || $data['errcode']==40001){
  278. $access_token = $this->access_token(true);
  279. return $this->create_menu($post_data);
  280. }
  281. //返回结果
  282. if($data['errcode']==0&&$data['errmsg']=='ok'){
  283. $result = array('status'=>1,'data'=>$data);
  284. return $result;
  285. }
  286. $result = array('status'=>40014,'data'=>$data);
  287. return $result;
  288. }
  289. /**
  290. * 自定义菜单查询接口
  291. * @author bug <3164145970@qq.com>
  292. * @createtime 2017-07-26 14:17:05
  293. * @return json 菜单列表
  294. */
  295. public function get_menu(){
  296. //获取access_token
  297. $access_token= $this->access_token(false);
  298. if($access_token['status']!=1 && $access_token['status']!=2){
  299. return $access_token;
  300. }
  301. //配置请求url,加入access_token参数
  302. $url = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token='.$access_token['data'];
  303. //获取请求结果,并将请求结果转换成json
  304. $data = string_json($url);
  305. if(array_key_exists('errcode', $data)){
  306. //access_token 过期重新获取并重新回调当前函数
  307. if($data['errcode']==42001 || $data['errcode']==40001){
  308. $access_token = $this->access_token(true);
  309. return $this->get_menu();
  310. }
  311. $result = array('status'=>40014,'data'=>$data);
  312. return $result;
  313. }
  314. //返回结果
  315. $result = array('status'=>1,'data'=>$data);
  316. return $result;
  317. }
  318. /**
  319. * 自定义菜单删除接口
  320. * @author bug <3164145970@qq.com>
  321. * @createtime 2017-07-26 14:17:05
  322. * @return json 请求结果
  323. */
  324. public function delete_menu(){
  325. //获取access_token
  326. $access_token= $this->access_token(false);
  327. if($access_token['status']!=1 && $access_token['status']!=2){
  328. return $access_token;
  329. }
  330. //配置请求url,加入access_token参数
  331. $url = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token='.$access_token['data'];
  332. //获取请求结果,并将请求结果转换成json
  333. $data = string_json($url);
  334. //access_token 过期重新获取并重新回调当前函数
  335. if($data['errcode']==42001 || $data['errcode']==40001){
  336. $access_token = $this->access_token(true);
  337. return $this->delete_menu();
  338. }
  339. $status = $data['errcode']==0?1:40014;
  340. //返回结果
  341. $result = array('status'=>$status,'data'=>$data);
  342. return $result;
  343. }
  344. /**
  345. * 获取自定义菜单配置接口
  346. * @author bug <3164145970@qq.com>
  347. * @createtime 2017-07-26 14:17:05
  348. * @return json 菜单列表
  349. */
  350. public function menu_config(){
  351. //获取access_token
  352. $access_token= $this->access_token(false);
  353. if($access_token['status']!=1 && $access_token['status']!=2){
  354. return $access_token;
  355. }
  356. //配置请求url,加入access_token参数
  357. $url = 'https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token='.$access_token['data'];
  358. //获取请求结果,并将请求结果转换成json
  359. $data = string_json($url);
  360. if(array_key_exists('errcode', $data)){
  361. //access_token 过期重新获取并重新回调当前函数
  362. if($data['errcode']==42001 || $data['errcode']==40001){
  363. $access_token = $this->access_token(true);
  364. return $this->menu_config();
  365. }
  366. $result = array('status'=>40014,'data'=>$data);
  367. return $result;
  368. }
  369. //返回结果
  370. $result = array('status'=>1,'data'=>$data);
  371. return $result;
  372. }
  373. /**********************自定义菜单 结束********/
  374. /**********************消息管理 开始********/
  375. /**
  376. * 消息/事件推送处理
  377. * @author bug <3164145970@qq.com>
  378. * @createtime 2017-08-16 15:58:42
  379. * @param poststr xml 推送数据字符串
  380. * @return [type] [description]
  381. */
  382. public function responseMsg($poststr){
  383. //如果推送消息 或者推送事件存在,进行处理
  384. if(!empty($poststr)){
  385. libxml_disable_entity_loader(true);
  386. $postObj = simplexml_load_string($poststr, 'SimpleXMLElement', LIBXML_NOCDATA);
  387. $msgType = $postObj->MsgType;
  388. //判断事件类型,进行对应事件类型处理
  389. switch ($msgType) {
  390. case 'text':
  391. $resultStr = $this->handleText($postObj);
  392. break;
  393. case 'image':
  394. $resultStr = $this->handleImage($postObj);
  395. break;
  396. case 'voice':
  397. $resultStr = $this->handleVoice($postObj);
  398. break;
  399. case 'video':
  400. $resultStr = $this->handleVideo($postObj);
  401. break;
  402. case 'shortvideo':
  403. $resultStr = $this->handleShortVideo($postObj);
  404. break;
  405. case 'location':
  406. $resultStr = $this->handleLocation($postObj);
  407. break;
  408. case 'link':
  409. $resultStr = $this->handleLink($postObj);
  410. break;
  411. case 'event':
  412. $resultStr = $this->handleEvent($postObj);
  413. break;
  414. default:
  415. $resultStr = "Unknow msg type: ".$msgType;
  416. break;
  417. }
  418. return $resultStr;
  419. }
  420. }
  421. /**---------------------------------------------------------接收消息-接收普通消息 开始-------------------------------------------------------------**/
  422. /**
  423. * 接收文本消息
  424. * @author bug <3164145970@qq.com>
  425. * @createtime 2017-08-16 17:22:58
  426. * @param postObj object 推送事件对象
  427. * @return [type] [description]
  428. */
  429. public function handleText($postObj){
  430. $contentStr = "您发送了文本消息:".$postObj->Content;
  431. return $this->responseText($postObj,$contentStr);
  432. }
  433. /**
  434. * 接收图片消息
  435. * @author bug <3164145970@qq.com>
  436. * @createtime 2017-08-16 17:22:58
  437. * @param postObj object 推送事件对象
  438. * @return [type] [description]
  439. */
  440. public function handleImage($postObj){
  441. $contentStr = "您发送了图片,图片链接:".$postObj->PicUrl.",图片消息媒体id:".$postObj->MediaId.",消息id:".$postObj->MsgId;
  442. return $this->responseText($postObj,$contentStr);
  443. }
  444. /**
  445. * 接收语音消息
  446. * @author bug <3164145970@qq.com>
  447. * @createtime 2017-08-16 17:22:58
  448. * @param postObj object 推送事件对象
  449. * @return [type] [description]
  450. */
  451. public function handleVoice($postObj){
  452. $contentStr = "您发送了语音,语音消息媒体id:".$postObj->MediaId.",语音格式:".$postObj->Format.",消息id".$postObj->MsgId.",Recognition:".$postObj->Recognition;
  453. return $this->responseText($postObj,$contentStr);
  454. }
  455. /**
  456. * 接收视频消息
  457. * @author bug <3164145970@qq.com>
  458. * @createtime 2017-08-16 17:22:58
  459. * @param postObj object 推送事件对象
  460. * @return [type] [description]
  461. */
  462. public function handleVideo($postObj){
  463. $contentStr = "您发送了视频,语音消息媒体id:".$postObj->MediaId.",视频消息缩略图的媒体id:".$postObj->ThumbMediaId.",消息id".$postObj->MsgId;
  464. return $this->responseText($postObj,$contentStr);
  465. }
  466. /**
  467. * 接收小视频消息
  468. * @author bug <3164145970@qq.com>
  469. * @createtime 2017-08-16 17:22:58
  470. * @param postObj object 推送事件对象
  471. * @return [type] [description]
  472. */
  473. public function handleShortVideo($postObj){
  474. $contentStr = "您发送了小视频,语音消息媒体id:".$postObj->MediaId.",视频消息缩略图的媒体id:".$postObj->ThumbMediaId.",消息id".$postObj->MsgId;
  475. return $this->responseText($postObj,$contentStr);
  476. }
  477. /**
  478. * 接收地理位置消息
  479. * @author bug <3164145970@qq.com>
  480. * @createtime 2017-08-16 17:22:58
  481. * @param postObj object 推送事件对象
  482. * @return [type] [description]
  483. */
  484. public function handleLocation($postObj){
  485. $contentStr = "您发送了地理位置,地理位置维度:".$postObj->Location_X.",地理位置经度:".$postObj->Location_Y.",地图缩放大小:".$postObj->Scale.",地理位置信息:".$postObj->Label.",消息id:".$postObj->MsgId;
  486. return $this->responseText($postObj,$contentStr);
  487. }
  488. /**
  489. * 接收链接消息
  490. * @author bug <3164145970@qq.com>
  491. * @createtime 2017-08-16 17:22:58
  492. * @param postObj object 推送事件对象
  493. * @return [type] [description]
  494. */
  495. public function handleLink($postObj){
  496. $contentStr = "您发送了链接,消息标题:".$postObj->Title.",消息描述:".$postObj->Description.",消息链接:".$postObj->Url.",消息id:".$postObj->MsgId;
  497. return $this->responseText($postObj,$contentStr);
  498. }
  499. /**---------------------------------------------------------接收消息-接收普通消息 结束-------------------------------------------------------------**/
  500. /**---------------------------------------------接收消息-接收事件推送 开始-------------------------------------------------------------**/
  501. /**
  502. * 接收事件推送
  503. * @author bug <3164145970@qq.com>
  504. * @createtime 2017-08-16 17:22:58
  505. * @param postObj object 推送事件对象
  506. * @return [type] [description]
  507. */
  508. public function handleEvent($postObj){
  509. $event = $postObj->Event;
  510. switch ($event) {
  511. case 'subscribe'://关注
  512. break;
  513. case 'unsubscribe'://取消关注
  514. break;
  515. case 'scancode_waitmsg'://扫描二维码
  516. break;
  517. case 'SCAN':
  518. break;
  519. case 'LOCATION':
  520. break;
  521. case 'VIEW':
  522. break;
  523. default:
  524. # code...
  525. break;
  526. }
  527. $contentStr = "您触发了事件:".$event;
  528. return $this->responseText($postObj,$contentStr);
  529. }
  530. /**------------------------------------------------------------接收消息-接收事件推送 结束-------------------------------------------------------------**/
  531. /**------------------------------------------------------发送消息-被动回复用户消息 开始-------------------------------------------------------------**/
  532. /**
  533. * 推送事件回复文本消息
  534. * @author bug <3164145970@qq.com>
  535. * @createtime 2017-08-16 16:05:33
  536. * @param object 接收的推送对象
  537. * @param content string 回复的文本消息
  538. * @return [type] [description]
  539. */
  540. public function responseText($object,$content)
  541. {
  542. $textTpl = "<xml>
  543. <ToUserName><![CDATA[%s]]></ToUserName>
  544. <FromUserName><![CDATA[%s]]></FromUserName>
  545. <CreateTime>%s</CreateTime>
  546. <MsgType><![CDATA[text]]></MsgType>
  547. <Content><![CDATA[%s]]></Content>
  548. </xml>";
  549. $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(),$content);
  550. return $resultStr;
  551. }
  552. /**
  553. * 推送事件回复图片消息
  554. * @author bug <3164145970@qq.com>
  555. * @createtime 2017-08-16 16:05:33
  556. * @param object 接收的推送对象
  557. * @param MediaId 通过素材管理中的接口上传多媒体文件,得到的id
  558. * @return [type] [description]
  559. */
  560. public function responseImage($object,$media_id)
  561. {
  562. $textTpl = "<xml>
  563. <ToUserName><![CDATA[%s]]></ToUserName>
  564. <FromUserName><![CDATA[%s]]></FromUserName>
  565. <CreateTime>%s</CreateTime>
  566. <MsgType><![CDATA[image]]></MsgType>
  567. <Image>
  568. <MediaId><![CDATA[media_id]]></MediaId>
  569. </Image>
  570. </xml>";
  571. $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(),$media_id);
  572. return $resultStr;
  573. }
  574. /**
  575. * 推送事件回复语音消息
  576. * @author bug <3164145970@qq.com>
  577. * @createtime 2017-08-16 16:05:33
  578. * @param object 接收的推送对象
  579. * @param MediaId 通过素材管理中的接口上传多媒体文件,得到的id
  580. * @return [type] [description]
  581. */
  582. public function responseVoice($object,$media_id)
  583. {
  584. $textTpl = "<xml>
  585. <ToUserName><![CDATA[%s]]></ToUserName>
  586. <FromUserName><![CDATA[%s]]></FromUserName>
  587. <CreateTime>%s</CreateTime>
  588. <MsgType><![CDATA[voice]]></MsgType>
  589. <Voice>
  590. <MediaId><![CDATA[%s]]></MediaId>
  591. </Voice>
  592. </xml>";
  593. $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(),$media_id);
  594. return $resultStr;
  595. }
  596. /**
  597. * 推送事件回复视频消息
  598. * @author bug <3164145970@qq.com>
  599. * @createtime 2017-08-16 16:05:33
  600. * @param object 接收的推送对象
  601. * @param media_id 通过素材管理中的接口上传多媒体文件,得到的id
  602. * @param title 视频消息的标题
  603. * @param description 视频消息的描述
  604. * @return
  605. */
  606. public function responseVideo($object,$media_id,$title='',$description='')
  607. {
  608. $textTpl = "<xml>
  609. <ToUserName><![CDATA[%s]]></ToUserName>
  610. <FromUserName><![CDATA[%s]]></FromUserName>
  611. <CreateTime>%s</CreateTime>
  612. <MsgType><![CDATA[video]]></MsgType>
  613. <Video>
  614. <MediaId><![CDATA[%s]]></MediaId>
  615. <Title><![CDATA[%s]]></Title>
  616. <Description><![CDATA[%s]]></Description>
  617. </Video>
  618. </xml>";
  619. $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(),$media_id,$title,$description);
  620. return $resultStr;
  621. }
  622. /**
  623. * 推送事件回复音乐消息
  624. * @author bug <3164145970@qq.com>
  625. * @createtime 2017-08-16 16:05:33
  626. * @param object 接收的推送对象
  627. * @param media_id 缩略图的媒体id,通过素材管理中的接口上传多媒体文件,得到的id
  628. * @param title 音乐标题
  629. * @param description 音乐描述
  630. * @param music_url 音乐链接
  631. * @param hqmusic_url 高质量音乐链接,WIFI环境优先使用该链接播放音乐
  632. * @return
  633. */
  634. public function responseMusic($object,$media_id,$title='',$description='',$music_url='',$hqmusic_url='')
  635. {
  636. $textTpl = "<xml>
  637. <ToUserName><![CDATA[%s]]></ToUserName>
  638. <FromUserName><![CDATA[%s]]></FromUserName>
  639. <CreateTime>%s</CreateTime>
  640. <MsgType><![CDATA[music]]></MsgType>
  641. <Music>
  642. <Title><![CDATA[TITLE]]></Title>
  643. <Description><![CDATA[DESCRIPTION]]></Description>
  644. <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
  645. <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
  646. <ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
  647. </Music>
  648. </xml>";
  649. $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(),$title,$description,$music_url,$hqmusic_url,$media_id);
  650. return $resultStr;
  651. }
  652. /**
  653. * 推送事件回复图文消息
  654. * @author bug <3164145970@qq.com>
  655. * @createtime 2017-08-16 16:05:33
  656. * @param object 接收的推送对象
  657. * @param articles 图文消息数组
  658. * @param article_count 图文消息个数,限制为8条以内
  659. * @param title 图文消息标题
  660. * @param description 图文消息描述
  661. * @param pic_url 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
  662. * @param url 点击图文消息跳转链接
  663. * @return
  664. */
  665. public function responseNews($object,$articles)
  666. {
  667. $article_count = count($articles);
  668. $textTpl = "<xml>
  669. <ToUserName><![CDATA[%s]]></ToUserName>
  670. <FromUserName><![CDATA[%s]]></FromUserName>
  671. <CreateTime>%s</CreateTime>
  672. <MsgType><![CDATA[news]]></MsgType>
  673. <ArticleCount>%s</ArticleCount>
  674. <Articles>";
  675. $textTpl = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(),$article_count);
  676. $article_tpl ="<item>
  677. <Title><![CDATA[%s]]></Title>
  678. <Description><![CDATA[%s]]></Description>
  679. <PicUrl><![CDATA[%s]]></PicUrl>
  680. <Url><![CDATA[%s]]></Url>
  681. </item>";
  682. foreach ($articles as $value) {
  683. $article_str = sprintf($article_tpl,$value['title'],$value['description'],$value['picurl'],$value['url']);
  684. $textTpl .= $article_str;
  685. }
  686. $textTpl .= "</Articles>
  687. </xml>";
  688. return $textTpl;
  689. }
  690. /**--------------------------------------------------------发送消息-被动回复用户消息 结束-------------------------------------------------------------**/
  691. /**
  692. * 客服接口-发消息
  693. * @author bug <3164145970@qq.com>
  694. * @createtime 2017-07-28 09:27:56
  695. * @param openid string 微信用户唯一凭证openid
  696. * @param type string 1 文本 2图文
  697. * @param data json 请求数据集
  698. * @return [type] [description]
  699. */
  700. public function custom_send($openid,$type,$msg,$customservice=''){
  701. //获取access_token
  702. $access_token= $this->access_token(false);
  703. if($access_token['status']!=1 && $access_token['status']!=2){
  704. return $access_token;
  705. }
  706. //配置请求url,加入access_token参数
  707. $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.$access_token['data'];
  708. $post_data['touser'] = $openid;
  709. $post_data['msgtype'] = $type;
  710. switch ($type) {
  711. case 'text'://发送文本消息
  712. $post_data['text']['content'] = $msg;
  713. break;
  714. case 'image'://发送图片消息
  715. $post_data['image']['media_id'] = $msg;
  716. break;
  717. case 'voice'://发送语音消息
  718. $post_data['voice']['media_id'] = $msg;
  719. break;
  720. case 'video'://发送视频消息,参数media_id,thumb_media_id,title,description
  721. $post_data['video'] = $msg;
  722. break;
  723. case 'music'://发送音乐消息,参数title,description,musicurl,hqmusicurl,thumb_media_id
  724. $post_data['music'] = $msg;
  725. break;
  726. case 'news'://发送图文消息(点击跳转到外链) 图文消息条数限制在8条以内,注意,如果图文数超过8,则将会无响应
  727. $post_data['news']['articles'] =$msg;
  728. break;
  729. case 'mpnews'://发送图文消息(点击跳转到图文消息页面) 图文消息条数限制在8条以内,注意,如果图文数超过8,则将会无响应
  730. $post_data['mpnews']['media_id'] = $msg;
  731. break;
  732. case 'wxcard'://发送卡券
  733. $post_data['wxcard']['card_id'] = $msg;
  734. break;
  735. case 'miniprogrampage'://发送小程序卡片,参数title,appid,pagepath,thumb_media_id
  736. $post_data['miniprogrampage'] = $msg;
  737. break;
  738. default:
  739. $post_data['msgtype'] = 'text';
  740. $post_data['text']['content'] = '这是一个默认图文消息:无消息类型';
  741. break;
  742. }
  743. //请注意,如果需要以某个客服帐号来发消息(在微信6.0.2及以上版本中显示自定义头像),则需在JSON数据包的后半部分加入customservice参数
  744. if(!empty($customservice)){
  745. $post_data['customservice']['kf_account'] = $customservice;
  746. }
  747. //将json数组转换成字符串数组
  748. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  749. //获取请求结果,并将请求结果转换成json
  750. $data = json_decode(https_request($url,$post_data),true);
  751. //access_token 过期重新获取并重新回调当前函数
  752. if($data['errcode']==42001 || $data['errcode']==40001){
  753. $access_token = $this->access_token(true);
  754. return $this->custom_send($openid,$type,$msg,$customservice);
  755. }
  756. //返回结果
  757. if($data['errcode']==0&&$data['errmsg']=='ok'){
  758. $result = array('status'=>1,'data'=>$data);
  759. return $result;
  760. }
  761. $result = array('status'=>40014,'data'=>$data);
  762. return $result;
  763. }
  764. /**
  765. * 获取模板列表
  766. * @author bug <3164145970@qq.com>
  767. * @createtime 2017-08-25 14:43:54
  768. * @param access_token 微信调用接口唯一凭证
  769. * @return json
  770. */
  771. public function template_list(){
  772. //获取access_token
  773. $access_token= $this->access_token(false);
  774. if($access_token['status']!=1 && $access_token['status']!=2){
  775. return $access_token;
  776. }
  777. //配置请求url,加入access_token参数
  778. $url = 'https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token='.$access_token['data'];
  779. //获取请求结果,并将请求结果转换成json
  780. $data = string_json($url);
  781. if(array_key_exists('errcode', $data)){
  782. //access_token 过期重新获取并重新回调当前函数
  783. if($data['errcode']==42001 || $data['errcode']==40001){
  784. $access_token = $this->access_token(true);
  785. return $this->template_list();
  786. }
  787. $result = array('status'=>40014,'data'=>$data);
  788. return $result;
  789. }
  790. //返回结果
  791. $result = array('status'=>1,'data'=>$data);
  792. return $result;
  793. }
  794. /**
  795. * 模板接口-发消息
  796. * @author bug <3164145970@qq.com>
  797. * @createtime 2017-08-01 15:50:11
  798. * @param data json 请求数据集
  799. * @return [type] [description]
  800. */
  801. public function template_send($post_data){
  802. //获取access_token
  803. $access_token= $this->access_token(false);
  804. if($access_token['status']!=1 && $access_token['status']!=2){
  805. return $access_token;
  806. }
  807. //配置请求url,加入access_token参数
  808. $url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$access_token['data'];
  809. //将json数组转换成字符串数组
  810. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  811. //获取请求结果,并将请求结果转换成json
  812. $data = json_decode(https_request($url,$post_data),true);
  813. //access_token 过期重新获取并重新回调当前函数
  814. if($data['errcode']==42001 || $data['errcode']==40001){
  815. $access_token = $this->access_token(true);
  816. return $this->template_send($post_data);
  817. }
  818. //返回结果
  819. if($data['errcode']==0&&$data['errmsg']=='ok'){
  820. $result = array('status'=>1,'data'=>$data);
  821. return $result;
  822. }
  823. $result = array('status'=>40014,'data'=>$data);
  824. return $result;
  825. }
  826. /**********************消息管理 结束********/
  827. /**********************微信网页授权 开始********/
  828. /**
  829. * 通过微信授权code获取微信用户access_token
  830. * @author bug <3164145970@qq.com>
  831. * @createtime 2017-07-27 11:26:30
  832. * @param code 微信用户授权获取的code
  833. * @return json 返回结果
  834. */
  835. public function user_access_token($code){
  836. //session开始
  837. if(!isset($_SESSION)){
  838. session_start();
  839. }
  840. //如果code已经被使用过了返回缓存里面的微信用户access_token相关信息
  841. if(isset($_SESSION['user_access_token'])&&$code==$_SESSION['user_access_token']['code']){
  842. $data = $_SESSION['user_access_token'];
  843. $result = array('status'=>2,'data'=>$data);
  844. return $result;
  845. }
  846. //配置请求url,加入access_token参数
  847. $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$this->appid.'&secret='.$this->appsecret.'&code='.$code.'&grant_type=authorization_code';
  848. //获取请求结果,并将请求结果转换成json
  849. $data = string_json($url);
  850. //获取当前时间
  851. $time = time();
  852. if(array_key_exists('errcode', $data)){
  853. $result = array('status'=>40014,'data'=>$data);
  854. return $result;
  855. }
  856. session_set_cookie_params(60*5); //设置access_token在服务器session中缓存时间
  857. //添加access_token过期时间
  858. $data['access_endtime'] = $time+$data['expires_in'];
  859. //添加refresh_token过期时间
  860. $data['refresh_endtime'] = $time+60*60*24*30;
  861. $data['code'] = $code;
  862. $_SESSION['user_access_token'] = $data;
  863. //返回结果
  864. $result = array('status'=>1,'data'=>$data);
  865. return $result;
  866. }
  867. /**
  868. * 刷新微信用户access_token
  869. * @author bug <3164145970@qq.com>
  870. * @createtime 2017-07-27 11:26:27
  871. * @param refresh_token 微信用户用来刷新access_token用的
  872. * @param state int 微信用户获取access_token的state
  873. * @return json 返回结果
  874. */
  875. public function user_refresh_token($refresh_token,$state=0){
  876. //配置请求url,加入access_token参数
  877. $url = 'https://api.weixin.qq.com/sns/oauth2/refresh_token?appid='.$this->appid.'&grant_type=refresh_token&refresh_token='.$refresh_token;
  878. //获取请求结果,并将请求结果转换成json
  879. $data = string_json($url);
  880. //获取当前时间
  881. $time = time();
  882. if(array_key_exists('errcode', $data)){
  883. if($data['errcode']==42002){
  884. //如果超时重定向首页重新获取refresh_token
  885. header("location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=".config('crm_config.wechat_appid')."&redirect_uri=".urlencode(config('crm_config.user_accesstoken_uri'))."&response_type=code&scope=snsapi_base&state=".$state."#wechat_redirect");exit;
  886. }
  887. $result = array('status'=>40014,'data'=>$data);
  888. return $result;
  889. }
  890. //添加access_token过期时间
  891. $data['access_endtime'] = $time+$data['expires_in'];
  892. //返回结果
  893. $result = array('status'=>1,'data'=>$data);
  894. return $result;
  895. }
  896. /**
  897. * 拉取用户信息(需scope为 snsapi_userinfo)
  898. * @author bug <3164145970@qq.com>
  899. * @createtime 2017-07-27 11:26:27
  900. * @param string access_token 微信用户授权获取的access_token
  901. * @param string openid 微信用户唯一凭证
  902. * @return json 返回结果
  903. */
  904. public function userinfo($access_token,$openid){
  905. //配置请求url,加入access_token参数
  906. $url = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$access_token.'&openid='.$openid.'&lang=zh_CN';
  907. //获取请求结果,并将请求结果转换成json
  908. $data = string_json($url);
  909. if(array_key_exists('errcode', $data)){
  910. $result = array('status'=>40014,'data'=>$data);
  911. return $result;
  912. }
  913. //返回结果
  914. $result = array('status'=>1,'data'=>$data);
  915. return $result;
  916. }
  917. /**
  918. * 检验授权凭证(access_token)是否有效
  919. * @author bug <3164145970@qq.com>
  920. * @createtime 2017-07-27 11:26:27
  921. * @param string access_token 微信用户授权获取的access_token
  922. * @param string openid 微信用户唯一凭证
  923. * @return json 返回结果
  924. */
  925. public function auth($access_token,$openid){
  926. //配置请求url,加入access_token参数
  927. $url = 'https://api.weixin.qq.com/sns/auth?access_token='.$access_token.'&openid='.$openid;
  928. //获取请求结果,并将请求结果转换成json
  929. $data = string_json($url);
  930. //返回结果
  931. $status = $data['errcode']==0?1:40014;
  932. $result = array('status'=>$status,'data'=>$data);
  933. return $result;
  934. }
  935. /**********************微信网页授权 结束********/
  936. /**********************微信自定义分享 开始********/
  937. /**
  938. * 获取微信自定已分享配置参数包
  939. * @author bug <3164145970@qq.com>
  940. * @createtime 2017-08-05 14:21:04
  941. * @return array 配置参数包
  942. */
  943. public function getSignPackage() {
  944. $jsapiTicket = $this->getJsApiTicket();
  945. // 注意 URL 一定要动态获取,不能 hardcode.
  946. $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
  947. $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
  948. $timestamp = time();
  949. $nonceStr = $this->createNonceStr();
  950. // 这里参数的顺序要按照 key 值 ASCII 码升序排序
  951. $string = "jsapi_ticket=".$jsapiTicket."&noncestr=".$nonceStr."&timestamp=".$timestamp."&url=".$url;
  952. $signature = sha1($string);
  953. $signPackage = array(
  954. "appId" => $this->appid,
  955. "nonceStr" => $nonceStr,
  956. "timestamp" => $timestamp,
  957. "url" => $url,
  958. "signature" => $signature,
  959. "rawString" => $string
  960. );
  961. return $signPackage;
  962. }
  963. /**
  964. * 微信自定义分享随机字符串
  965. * @author bug <3164145970@qq.com>
  966. * @createtime 2017-08-05 14:22:15
  967. * @param length int 随机字符串长度
  968. * @return str string 随机字符串
  969. */
  970. private function createNonceStr($length = 16) {
  971. $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  972. $str = "";
  973. for ($i = 0; $i < $length; $i++) {
  974. $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  975. }
  976. return $str;
  977. }
  978. /**
  979. * 微信自定义分享获取jsapiticket
  980. * @author bug <3164145970@qq.com>
  981. * @createtime 2017-08-05 14:23:30
  982. * @return jsapi_ticket string 微信jsapi调用凭证
  983. */
  984. private function getJsApiTicket() {
  985. // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
  986. $data = json_decode(file_get_contents(dirname(__FILE__)."/json/jsapi_ticket.json"));
  987. if ($data->expire_time < time()) {
  988. $access_token = $this->access_token(false);
  989. if($access_token['status']!=1 && $access_token['status']!=2){
  990. return $access_token;
  991. }
  992. // 如果是企业号用以下 URL 获取 ticket
  993. // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=".$access_token['data'];
  994. $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$access_token['data'];
  995. $res = json_decode(https_get($url));
  996. if(!isset($res->ticket)){
  997. $access_token = $this->access_token(true);
  998. $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$access_token['data'];
  999. $res = json_decode(https_get($url));
  1000. }
  1001. $ticket = $res->ticket;
  1002. if ($ticket) {
  1003. $data->expire_time = time() + 7200;
  1004. $data->jsapi_ticket = $ticket;
  1005. $fp = fopen(dirname(__FILE__)."/json/jsapi_ticket.json", "w");
  1006. fwrite($fp, json_encode($data));
  1007. fclose($fp);
  1008. }
  1009. } else {
  1010. $ticket = $data->jsapi_ticket;
  1011. }
  1012. return $ticket;
  1013. }
  1014. /**********************微信自定义分享 结束********/
  1015. /**********************素材管理 开始********/
  1016. /**
  1017. * 获取永久素材列表
  1018. * @author bug <3164145970@qq.com>
  1019. * @createtime 2017-09-02 16:44:24
  1020. * @param type string 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
  1021. * @param offset int 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
  1022. * @param count int 返回素材的数量,取值在1到20之间
  1023. * @return [type] [description]
  1024. */
  1025. public function material_list($type,$offset=0,$count=20){
  1026. //获取access_token
  1027. $access_token= $this->access_token(false);
  1028. if($access_token['status']!=1 && $access_token['status']!=2){
  1029. return $access_token;
  1030. }
  1031. //组装参数
  1032. $post_data['type'] = $type;
  1033. $post_data['offset'] = $offset;
  1034. $post_data['count'] = $count;
  1035. //配置请求url,加入access_token参数
  1036. $url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token='.$access_token['data'];
  1037. //将json数组转换成字符串数组
  1038. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  1039. //获取请求结果,并将请求结果转换成json
  1040. $data = json_decode(https_request($url,$post_data),true);
  1041. //access_token 过期重新获取并重新回调当前函数
  1042. if(isset($data['errcode']) && ($data['errcode']==42001 || $data['errcode']==40001)){
  1043. $access_token = $this->access_token(true);
  1044. return $this->create_menu($type,$offset,$count);
  1045. }
  1046. //返回结果
  1047. if(!isset($data['errcode'])){
  1048. $result = array('status'=>1,'data'=>$data);
  1049. return $result;
  1050. }
  1051. $result = array('status'=>40014,'data'=>$data);
  1052. return $result;
  1053. }
  1054. /**********************素材管理 结束********/
  1055. /**********************用户管理 开始********/
  1056. /**
  1057. * 获取关注用户个人信息
  1058. * @author bug <3164145970@qq.com>
  1059. * @createtime 2017-08-25 14:43:54
  1060. * @param access_token string 微信调用接口唯一凭证
  1061. * @param openid string 用户的openid
  1062. * @return json
  1063. */
  1064. public function user_info($openid=''){
  1065. //获取access_token
  1066. $access_token= $this->access_token(false);
  1067. if($access_token['status']!=1 && $access_token['status']!=2){
  1068. return $access_token;
  1069. }
  1070. //配置请求url,加入access_token参数
  1071. $url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$access_token['data'].'&openid='.$openid.'&lang=zh_CN ';
  1072. //获取请求结果,并将请求结果转换成json
  1073. $data = string_json($url);
  1074. if(array_key_exists('errcode', $data)){
  1075. //access_token 过期重新获取并重新回调当前函数
  1076. if($data['errcode']==42001 || $data['errcode']==40001 ){
  1077. $access_token = $this->access_token(true);
  1078. return $this->user_info($openid);
  1079. }
  1080. $result = array('status'=>40014,'data'=>$data);
  1081. return $result;
  1082. }
  1083. //返回结果
  1084. $result = array('status'=>1,'data'=>$data);
  1085. return $result;
  1086. }
  1087. /**
  1088. * 批量获取用户信息
  1089. * @author bug <3164145970@qq.com>
  1090. * @createtime 2017-10-16 14:20:46
  1091. * @param data json 请求数据集
  1092. * @return [type] [description]
  1093. */
  1094. public function user_list_info($post_data){
  1095. //获取access_token
  1096. $access_token= $this->access_token(false);
  1097. if($access_token['status']!=1 && $access_token['status']!=2){
  1098. return $access_token;
  1099. }
  1100. //配置请求url,加入access_token参数
  1101. $url = 'https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token='.$access_token['data'];
  1102. //将json数组转换成字符串数组
  1103. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  1104. //获取请求结果,并将请求结果转换成json
  1105. $data = json_decode(https_request($url,$post_data),true);
  1106. //access_token 过期重新获取并重新回调当前函数
  1107. if(isset($data['errcode'])&&($data['errcode']==42001 || $data['errcode']==40001)){
  1108. $access_token = $this->access_token(true);
  1109. return $this->user_list_info($post_data);
  1110. }
  1111. //返回结果
  1112. if(isset($data['user_info_list'])){
  1113. $result = array('status'=>1,'data'=>$data);
  1114. return $result;
  1115. }
  1116. $result = array('status'=>40014,'data'=>$data);
  1117. return $result;
  1118. }
  1119. /**
  1120. * 获取关注用户列表
  1121. * @author bug <3164145970@qq.com>
  1122. * @createtime 2017-08-25 14:43:54
  1123. * @param access_token string 微信调用接口唯一凭证
  1124. * @param next_openid string 上次请求最后一个用户的openid
  1125. * @return json
  1126. */
  1127. public function user_list($next_openid=''){
  1128. //获取access_token
  1129. $access_token= $this->access_token(false);
  1130. if($access_token['status']!=1 && $access_token['status']!=2){
  1131. return $access_token;
  1132. }
  1133. //配置请求url,加入access_token参数
  1134. $url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token='.$access_token['data'];
  1135. if(!empty($next_openid)){
  1136. $url.='&next_openid='.$next_openid;
  1137. }
  1138. //获取请求结果,并将请求结果转换成json
  1139. $data = string_json($url);
  1140. if(array_key_exists('errcode', $data)){
  1141. //access_token 过期重新获取并重新回调当前函数
  1142. if($data['errcode']==42001 || $data['errcode']==40001){
  1143. $access_token = $this->access_token(true);
  1144. return $this->user_list($next_openid);
  1145. }
  1146. $result = array('status'=>40014,'data'=>$data);
  1147. return $result;
  1148. }
  1149. //返回结果
  1150. $result = array('status'=>1,'data'=>$data);
  1151. return $result;
  1152. }
  1153. /**********************用户管理 结束********/
  1154. /**********************新版客服 开始********/
  1155. /**
  1156. * 添加客服账号
  1157. * @author bug <3164145970@qq.com>
  1158. * @createtime 2017-08-02 15:39:36
  1159. * @param post_data 请求数据
  1160. * @param kf_account string 完整客服帐号,格式为:帐号前缀@公众号微信号,帐号前缀最多10个字符,必须是英文、数字字符或者下划线,后缀为公众号微信号,长度不超过30个字符
  1161. * @param nickname 客服昵称,最长16个字
  1162. * @return [type] [description]
  1163. */
  1164. public function customservice_add($post_data){
  1165. //获取access_token
  1166. $access_token= $this->access_token(false);
  1167. if($access_token['status']!=1 && $access_token['status']!=2){
  1168. return $access_token;
  1169. }
  1170. //配置请求url,加入access_token参数
  1171. $url = 'https://api.weixin.qq.com/customservice/kfaccount/add?access_token='.$access_token['data'];
  1172. //将json数组转换成字符串数组
  1173. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  1174. //获取请求结果,并将请求结果转换成json
  1175. $data = json_decode(https_request($url,$post_data),true);
  1176. //access_token 过期重新获取并重新回调当前函数
  1177. if($data['errcode']==42001 || $data['errcode']==40001){
  1178. $access_token = $this->access_token(true);
  1179. return $this->customservice_add($post_data);
  1180. }
  1181. //返回结果
  1182. if($data['errcode']==0&&$data['errmsg']=='ok'){
  1183. $result = array('status'=>1,'data'=>$data);
  1184. return $result;
  1185. }
  1186. $result = array('status'=>40014,'data'=>$data);
  1187. return $result;
  1188. }
  1189. /**
  1190. * 获取聊天记录
  1191. * @author bug <3164145970@qq.com>
  1192. * @createtime 2017-08-01 17:20:03
  1193. * @param starttime int 起始时间,unix时间戳
  1194. * @param endtime int 结束时间,unix时间戳,每次查询时段不能超过24小时
  1195. * @param msgid int 消息id顺序从小到大,从1开始
  1196. * @param number int 每次获取条数,最多10000条
  1197. * @return json 返回结果
  1198. */
  1199. public function customservice_getmsglist($starttime,$endtime,$msgid,$number){
  1200. //获取access_token
  1201. $access_token= $this->access_token(false);
  1202. if($access_token['status']!=1 && $access_token['status']!=2){
  1203. return $access_token;
  1204. }
  1205. //配置请求url,加入access_token参数
  1206. $url = 'https://api.weixin.qq.com/customservice/msgrecord/getmsglist?access_token='.$access_token['data'];
  1207. //将json数组转换成字符串数组
  1208. $post_data = array('starttime'=>$starttime,
  1209. 'endtime'=>$endtime,
  1210. 'msgid'=>$msgid,
  1211. 'number'=>$number);
  1212. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  1213. //获取请求结果,并将请求结果转换成json
  1214. $data = json_decode(https_request($url,$post_data),true);
  1215. //access_token 过期重新获取并重新回调当前函数
  1216. if(isset($data['errcode']) && ($data['errcode']==42001 || $data['errcode']==40001)){
  1217. $access_token = $this->access_token(true);
  1218. return $this->customservice_getmsglist($starttime,$endtime,$msgid,$number);
  1219. }
  1220. //返回结果
  1221. if(isset($data['recordlist'])){
  1222. $result = array('status'=>1,'data'=>$data);
  1223. return $result;
  1224. }
  1225. $result = array('status'=>40014,'data'=>$data);
  1226. return $result;
  1227. }
  1228. /**********************新版客服 结束********/
  1229. /**********************微信支付 开始********/
  1230. /**
  1231. * 统一下单,WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填
  1232. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1233. * @author bug <3164145970@qq.com>
  1234. * @createtime 2017-09-09 16:22:38\
  1235. * @param WxPayUnifiedOrder $inputObj
  1236. * @param int $timeOut
  1237. * @throws WxPayException
  1238. * @return [type] [description]
  1239. */
  1240. public function unifiedOrder($data, $timeOut = 6){
  1241. //配置请求url
  1242. $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
  1243. //检查请求参数
  1244. if(!isset($data['out_trade_no'])){
  1245. $result = array('status'=>40010,'data'=>'缺少统一支付接口必填参数out_trade_no!');
  1246. return $result;
  1247. }
  1248. if(!isset($data['body'])){
  1249. $result = array('status'=>40010,'data'=>'缺少统一支付接口必填参数body!');
  1250. return $result;
  1251. }
  1252. if(!isset($data['total_fee'])){
  1253. $result = array('status'=>40010,'data'=>'缺少统一支付接口必填参数total_fee!');
  1254. return $result;
  1255. }
  1256. if(!isset($data['trade_type'])){
  1257. $result = array('status'=>40010,'data'=>'缺少统一支付接口必填参数trade_type!');
  1258. return $result;
  1259. }
  1260. if($data['trade_type'] == 'JSAPI' && !isset($data['openid'])){
  1261. $result = array('status'=>40010,'data'=>'统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!');
  1262. return $result;
  1263. }
  1264. if($data['trade_type'] == "NATIVE" && !isset($data['product_id'])){
  1265. $result = array('status'=>40010,'data'=>'统一支付接口中,缺少必填参数product_id!trade_type为NATIVE时,product_id为必填参数!');
  1266. return $result;
  1267. }
  1268. //异步通知url未设置,则使用配置文件中的url
  1269. if(!isset($data['notify_url'])){
  1270. $data['notify_url'] = config('crm_config.wechat_notify_url');
  1271. }
  1272. $data['appid'] = $this->appid;//微信支付分配的公众账号ID(企业号corpid即为此appId)
  1273. $data['mch_id'] = $this->mch_id;//微信支付分配的商户号
  1274. $data['spbill_create_ip'] = get_client_ip();//APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP
  1275. $data['nonce_str'] = $this->createNonceStr(32);
  1276. $data['sign'] = $this->makeSign($data);
  1277. $xml = arr_xml($data);
  1278. $startTimeStamp = milli_time();//请求开始时间
  1279. $response = $this->postXml($xml, $url, false, $timeOut);
  1280. $datas = xml_arr($response);//将xml转为array
  1281. //判断请求结果是否成功
  1282. if($datas['return_code'] != 'SUCCESS'){
  1283. $result = array('status'=>40014,'data'=>$datas);
  1284. return $result;
  1285. }
  1286. //判断签名是否存在,及签名是否正确
  1287. if(!array_key_exists('sign', $datas)){
  1288. $result = array('status'=>40011,'data'=>'签名错误!');
  1289. return $result;
  1290. }
  1291. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1292. //返回结果
  1293. $result = array('status'=>1,'data'=>$datas);
  1294. return $result;
  1295. }
  1296. /**
  1297. * 查询订单,WxPayOrderQuery中out_trade_no、transaction_id至少填一个
  1298. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1299. * @author bug <3164145970@qq.com>
  1300. * @createtime 2017-09-11 11:37:20
  1301. * @param $data 参数集
  1302. * @param $timeOut 超时
  1303. * @return 成功时返回,其他抛异常
  1304. */
  1305. public function orderQuery($data, $timeOut = 6){
  1306. $url = "https://api.mch.weixin.qq.com/pay/orderquery";
  1307. //检测必填参数
  1308. if(!array_key_exists('out_trade_no', $data) && !array_key_exists('transaction_id', $data)) {
  1309. $result = array('status'=>40010,'data'=>'订单查询接口中,out_trade_no、transaction_id至少填一个!');
  1310. return $result;
  1311. }
  1312. //组装参数
  1313. $data['appid'] = $this->appid;//公众账号ID
  1314. $data['mch_id'] = $this->mch_id;//商户号
  1315. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1316. $data['sign'] = $this->makeSign($data);//签名
  1317. $xml = arr_xml($data);
  1318. $startTimeStamp = milli_time();//请求开始时间
  1319. $response = $this->postXml($xml, $url, false, $timeOut);
  1320. $datas = xml_arr($response);//将xml转为array
  1321. //判断请求结果是否成功
  1322. if($datas['return_code'] != 'SUCCESS'){
  1323. $result = array('status'=>40014,'data'=>$datas);
  1324. return $result;
  1325. }
  1326. //判断签名是否存在,及签名是否正确
  1327. if(!array_key_exists('sign', $datas) ){
  1328. $result = array('status'=>40011,'data'=>'签名错误!');
  1329. return $result;
  1330. }
  1331. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1332. //返回结果
  1333. $result = array('status'=>1,'data'=>$datas);
  1334. return $result;
  1335. }
  1336. /**
  1337. * 关闭订单,WxPayCloseOrder中out_trade_no必填
  1338. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1339. * @author bug <3164145970@qq.com>
  1340. * @createtime 2017-09-11 11:48:48
  1341. * @param $data 参数集
  1342. * @param $timeOut 超时
  1343. * @return 成功时返回,其他抛异常
  1344. */
  1345. public function closeOrder($data, $timeOut = 6){
  1346. $url = "https://api.mch.weixin.qq.com/pay/closeorder";
  1347. //检测必填参数
  1348. if(!array_key_exists('out_trade_no', $data)) {
  1349. $result = array('status'=>40010,'data'=>'订单关闭接口中,out_trade_no必填!');
  1350. return $result;
  1351. }
  1352. //组装参数
  1353. $data['appid'] = $this->appid;//公众账号ID
  1354. $data['mch_id'] = $this->mch_id;//商户号
  1355. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1356. $data['sign'] = $this->makeSign($data);//签名
  1357. $xml = arr_xml($data);
  1358. $startTimeStamp = milli_time();//请求开始时间
  1359. $response = $this->postXml($xml, $url, false, $timeOut);
  1360. $datas = xml_arr($response);//将xml转为array
  1361. //判断请求结果是否成功
  1362. if($datas['return_code'] != 'SUCCESS'){
  1363. $result = array('status'=>40014,'data'=>$datas);
  1364. return $result;
  1365. }
  1366. //判断签名是否存在,及签名是否正确
  1367. if(!array_key_exists('sign', $datas) ){
  1368. $result = array('status'=>40011,'data'=>'签名错误!');
  1369. return $result;
  1370. }
  1371. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1372. //返回结果
  1373. $result = array('status'=>1,'data'=>$datas);
  1374. return $result;
  1375. }
  1376. /**
  1377. * 申请退款,WxPayRefund中out_trade_no、transaction_id至少填一个且
  1378. * out_refund_no、total_fee、refund_fee、op_user_id为必填参数
  1379. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1380. * @author bug <3164145970@qq.com>
  1381. * @createtime 2017-09-11 13:42:49
  1382. * @param $data 参数集
  1383. * @param $timeOut 超时
  1384. * @return 成功时返回,其他抛异常
  1385. */
  1386. public function refund($data, $timeOut = 6){
  1387. $url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
  1388. //检测必填参数
  1389. if(!array_key_exists('out_trade_no', $data) && !array_key_exists('transaction_id', $data)) {
  1390. $result = array('status'=>40010,'data'=>'退款申请接口中,out_trade_no、transaction_id至少填一个!');
  1391. return $result;
  1392. }
  1393. if(!array_key_exists('out_refund_no', $data)) {
  1394. $result = array('status'=>40010,'data'=>'退款申请接口中,缺少必填参数out_refund_no!');
  1395. return $result;
  1396. }
  1397. if(!array_key_exists('total_fee', $data)) {
  1398. $result = array('status'=>40010,'data'=>'退款申请接口中,缺少必填参数total_fee!');
  1399. return $result;
  1400. }
  1401. if(!array_key_exists('refund_fee', $data)) {
  1402. $result = array('status'=>40010,'data'=>'退款申请接口中,缺少必填参数refund_fee!');
  1403. return $result;
  1404. }
  1405. //组装参数
  1406. $data['appid'] = $this->appid;//公众账号ID
  1407. $data['mch_id'] = $this->mch_id;//商户号
  1408. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1409. /**
  1410. * 仅针对老资金流商户使用
  1411. *REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款)
  1412. *REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款
  1413. */
  1414. $data['refund_account'] = 'REFUND_SOURCE_RECHARGE_FUNDS';//退款资金来源
  1415. $data['sign'] = $this->makeSign($data);//签名
  1416. $xml = arr_xml($data);
  1417. $startTimeStamp = milli_time();//请求开始时间
  1418. $response = $this->postXml($xml, $url, true, $timeOut);
  1419. $datas = xml_arr($response);//将xml转为array
  1420. //判断请求结果是否成功
  1421. if($datas['return_code'] != 'SUCCESS'){
  1422. $result = array('status'=>40014,'data'=>$datas);
  1423. return $result;
  1424. }
  1425. //判断签名是否存在,及签名是否正确
  1426. if(!array_key_exists('sign', $datas) ){
  1427. $result = array('status'=>40011,'data'=>'签名错误!');
  1428. return $result;
  1429. }
  1430. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1431. //返回结果
  1432. $result = array('status'=>1,'data'=>$datas);
  1433. return $result;
  1434. }
  1435. /**
  1436. * 查询退款
  1437. * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,
  1438. * 用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
  1439. * WxPayRefundQuery中out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个
  1440. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1441. * @author bug <3164145970@qq.com>
  1442. * @createtime 2017-09-11 13:56:23
  1443. * @param $data 参数集
  1444. * @param $timeOut 超时
  1445. * @return 成功时返回,其他抛异常
  1446. */
  1447. public function refundQuery($data, $timeOut = 6){
  1448. $url = "https://api.mch.weixin.qq.com/pay/refundquery";
  1449. //检测必填参数
  1450. if(!array_key_exists('out_refund_no', $data) && !array_key_exists('out_trade_no', $data) && !array_key_exists('transaction_id', $data) && !array_key_exists('refund_id', $data) ) {
  1451. $result = array('status'=>40010,'data'=>'退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个');
  1452. return $result;
  1453. }
  1454. //组装参数
  1455. $data['appid'] = $this->appid;//公众账号ID
  1456. $data['mch_id'] = $this->mch_id;//商户号
  1457. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1458. $data['sign'] = $this->makeSign($data);//签名
  1459. $xml = arr_xml($data);
  1460. $startTimeStamp = milli_time();//请求开始时间
  1461. $response = $this->postXml($xml, $url, false, $timeOut);
  1462. $datas = xml_arr($response);//将xml转为array
  1463. //判断请求结果是否成功
  1464. if($datas['return_code'] != 'SUCCESS'){
  1465. $result = array('status'=>40014,'data'=>$datas);
  1466. return $result;
  1467. }
  1468. //判断签名是否存在,及签名是否正确
  1469. if(!array_key_exists('sign', $datas) ){
  1470. $result = array('status'=>40011,'data'=>'签名错误!');
  1471. return $result;
  1472. }
  1473. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1474. //返回结果
  1475. $result = array('status'=>1,'data'=>$datas);
  1476. return $result;
  1477. }
  1478. /**
  1479. * 下载对账单,WxPayDownloadBill中bill_date为必填参数
  1480. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1481. * @author bug <3164145970@qq.com>
  1482. * @createtime 2017-09-11 14:04:10
  1483. * @param $data 参数集
  1484. * @param $timeOut 超时
  1485. * @return 成功时返回,其他抛异常
  1486. */
  1487. public function downloadBill($data, $timeOut = 6){
  1488. $url = "https://api.mch.weixin.qq.com/pay/downloadbill";
  1489. //检测必填参数
  1490. if(!array_key_exists('bill_date', $data)) {
  1491. $result = array('status'=>40010,'data'=>'对账单接口中,缺少必填参数bill_date!');
  1492. return $result;
  1493. }
  1494. //组装参数
  1495. $data['appid'] = $this->appid;//公众账号ID
  1496. $data['mch_id'] = $this->mch_id;//商户号
  1497. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1498. $data['sign'] = $this->makeSign($data);//签名
  1499. $xml = arr_xml($data);
  1500. $startTimeStamp = milli_time();//请求开始时间
  1501. $response = $this->postXml($xml, $url, false, $timeOut);
  1502. $datas = xml_arr($response);//将xml转为array
  1503. //判断请求结果是否成功
  1504. if($datas['return_code'] != 'SUCCESS'){
  1505. $result = array('status'=>40014,'data'=>$datas);
  1506. return $result;
  1507. }
  1508. //判断签名是否存在,及签名是否正确
  1509. if(!array_key_exists('sign', $datas) ){
  1510. $result = array('status'=>40011,'data'=>'签名错误!');
  1511. return $result;
  1512. }
  1513. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1514. //返回结果
  1515. $result = array('status'=>1,'data'=>$datas);
  1516. return $result;
  1517. }
  1518. /**
  1519. * 提交被扫支付API
  1520. * 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,
  1521. * 由商户收银台或者商户后台调用该接口发起支付。
  1522. * WxPayWxPayMicroPay中body、out_trade_no、total_fee、auth_code参数必填
  1523. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1524. * @author bug <3164145970@qq.com>
  1525. * @createtime 2017-09-11 14:06:11
  1526. * @param $data 参数集
  1527. * @param $timeOut 超时
  1528. * @return 成功时返回,其他抛异常
  1529. */
  1530. public function micropay($data, $timeOut = 6){
  1531. $url = "https://api.mch.weixin.qq.com/pay/micropay";
  1532. //检测必填参数
  1533. if(!array_key_exists('body', $data)) {
  1534. $result = array('status'=>40010,'data'=>'提交被扫支付API接口中,缺少必填参数body!');
  1535. return $result;
  1536. }
  1537. if(!array_key_exists('out_trade_no', $data)) {
  1538. $result = array('status'=>40010,'data'=>'提交被扫支付API接口中,缺少必填参数out_trade_no!');
  1539. return $result;
  1540. }
  1541. if(!array_key_exists('total_fee', $data)) {
  1542. $result = array('status'=>40010,'data'=>'提交被扫支付API接口中,缺少必填参数total_fee!');
  1543. return $result;
  1544. }
  1545. if(!array_key_exists('auth_code', $data)) {
  1546. $result = array('status'=>40010,'data'=>'提交被扫支付API接口中,缺少必填参数auth_code!');
  1547. return $result;
  1548. }
  1549. //组装参数
  1550. $data['spbill_create_ip'] = get_client_ip();//终端ip
  1551. $data['appid'] = $this->appid;//公众账号ID
  1552. $data['mch_id'] = $this->mch_id;//商户号
  1553. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1554. $data['sign'] = $this->makeSign($data);//签名
  1555. $xml = arr_xml($data);
  1556. $startTimeStamp = milli_time();//请求开始时间
  1557. $response = $this->postXml($xml, $url, false, $timeOut);
  1558. $datas = xml_arr($response);//将xml转为array
  1559. //判断请求结果是否成功
  1560. if($datas['return_code'] != 'SUCCESS'){
  1561. $result = array('status'=>40014,'data'=>$datas);
  1562. return $result;
  1563. }
  1564. //判断签名是否存在,及签名是否正确
  1565. if(!array_key_exists('sign', $datas) ){
  1566. $result = array('status'=>40011,'data'=>'签名错误!');
  1567. return $result;
  1568. }
  1569. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1570. //返回结果
  1571. $result = array('status'=>1,'data'=>$datas);
  1572. return $result;
  1573. }
  1574. /**
  1575. * 微信扫码支付模式一成功返回参数包装
  1576. * @author bug <3164145970@qq.com>
  1577. * @createtime 2017-09-16 16:22:40
  1578. * @param $data 参数集
  1579. * @return [type] [description]
  1580. */
  1581. public function native_pkg($data){
  1582. $data['nonce_str'] =$this->createNonceStr(32);//随机字符串
  1583. $data['sign'] = $this->makeSign($data);//签名
  1584. return $data;
  1585. }
  1586. /**
  1587. * 撤销订单API接口,WxPayReverse中参数out_trade_no和transaction_id必须填写一个
  1588. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1589. * @author bug <3164145970@qq.com>
  1590. * @createtime 2017-09-11 14:06:11
  1591. * @param $data 参数集
  1592. * @param $timeOut 超时
  1593. * @return 成功时返回,其他抛异常
  1594. */
  1595. public function reverse($data, $timeOut = 6){
  1596. $url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
  1597. //检测必填参数
  1598. if(!array_key_exists('out_trade_no', $data) && !array_key_exists('transaction_id', $data)) {
  1599. $result = array('status'=>40010,'data'=>'撤销订单API接口中,参数out_trade_no和transaction_id必须填写一个');
  1600. return $result;
  1601. }
  1602. //组装参数
  1603. $data['appid'] = $this->appid;//公众账号ID
  1604. $data['mch_id'] = $this->mch_id;//商户号
  1605. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1606. $data['sign'] = $this->makeSign($data);//签名
  1607. $xml = arr_xml($data);
  1608. $startTimeStamp = milli_time();//请求开始时间
  1609. $response = $this->postXml($xml, $url, false, $timeOut);
  1610. $datas = xml_arr($response);//将xml转为array
  1611. //判断请求结果是否成功
  1612. if($datas['return_code'] != 'SUCCESS'){
  1613. $result = array('status'=>40014,'data'=>$datas);
  1614. return $result;
  1615. }
  1616. //判断签名是否存在,及签名是否正确
  1617. if(!array_key_exists('sign', $datas) ){
  1618. $result = array('status'=>40011,'data'=>'签名错误!');
  1619. return $result;
  1620. }
  1621. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1622. //返回结果
  1623. $result = array('status'=>1,'data'=>$datas);
  1624. return $result;
  1625. }
  1626. /**
  1627. * 测速上报,该方法内部封装在report中,使用时请注意异常流程
  1628. * interface_url、return_code、result_code、user_ip、execute_time_必填
  1629. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1630. * @author bug <3164145970@qq.com>
  1631. * @createtime 2017-09-11 11:18:44
  1632. * @param $data 参数集
  1633. * @param $timeOut 超时
  1634. * @return 成功时返回,其他抛异常
  1635. */
  1636. private function report($data, $timeOut = 1)
  1637. {
  1638. $url = "https://api.mch.weixin.qq.com/payitil/report";
  1639. //检测必填参数
  1640. if(!array_key_exists('interface_url', $data)){
  1641. throw new Exception("接口URL,缺少必填参数interface_url!");
  1642. }
  1643. if(!array_key_exists('return_code', $data)){
  1644. throw new Exception("返回状态码,缺少必填参数return_code!");
  1645. }
  1646. if(!array_key_exists('result_code', $data)){
  1647. throw new Exception("业务结果,缺少必填参数result_code!");
  1648. }
  1649. if(!array_key_exists('user_ip', $data)){
  1650. throw new Exception("访问接口IP,缺少必填参数user_ip!");
  1651. }
  1652. if(!array_key_exists('execute_time_', $data)){
  1653. throw new Exception("接口耗时,缺少必填参数execute_time_!");
  1654. }
  1655. //组装参数
  1656. $data['appid'] = $this->appid;//公众账号ID
  1657. $data['mch_id'] = $this->mch_id;//商户号
  1658. $data['user_ip'] = get_client_ip();//终端ip
  1659. $data['time'] = date("YmdHis");//商户上报时间
  1660. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1661. $data['sign'] = $this->makeSign($data);//签名
  1662. $xml = arr_xml($data);
  1663. $startTimeStamp = milli_time();//请求开始时间
  1664. $response = $this->postXml($xml, $url, false, $timeOut);
  1665. return $response;
  1666. }
  1667. /**
  1668. * 生成二维码规则,模式一生成支付二维码
  1669. * appid、mchid、spbill_create_ip、nonce_str不需要填入2017-09-11 14:20:05
  1670. * @author bug <3164145970@qq.com>
  1671. * @createtime 2017-09-11 14:20:05
  1672. * @param $data 参数集
  1673. * @param $timeOut 超时
  1674. * @return 成功时返回,其他抛异常
  1675. */
  1676. private function bizpayurl($data, $timeOut = 6){
  1677. //检测必填参数
  1678. if(!array_key_exists('product_id', $data)) {
  1679. $result = array('status'=>40010,'data'=>'生成二维码,缺少必填参数product_id!');
  1680. return $result;
  1681. }
  1682. //组装参数
  1683. $data['appid'] = $this->appid;//公众账号ID
  1684. $data['mch_id'] = $this->mch_id;//商户号
  1685. $data['time_stamp'] = time();//时间戳
  1686. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1687. $data['sign'] = $this->makeSign($data);//签名
  1688. $result = array('status'=>1,'data'=>$data);
  1689. return $result;
  1690. }
  1691. /**
  1692. * 转换短链接
  1693. * 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),
  1694. * 减小二维码数据量,提升扫描速度和精确度。
  1695. * appid、mchid、spbill_create_ip、nonce_str不需要填入
  1696. * @author bug <3164145970@qq.com>
  1697. * @createtime 2017-09-11 14:41:02
  1698. * @param $data 参数集
  1699. * @param $timeOut 超时
  1700. * @return 成功时返回,其他抛异常
  1701. */
  1702. public function shorturl($data, $timeOut = 6){
  1703. $url = "https://api.mch.weixin.qq.com/tools/shorturl";
  1704. //检测必填参数
  1705. if(!array_key_exists('long_url', $data)) {
  1706. $result = array('status'=>40010,'data'=>'需要转换的URL,签名用原串,传输需URL encode!');
  1707. return $result;
  1708. }
  1709. //组装参数
  1710. $data['appid'] = $this->appid;//公众账号ID
  1711. $data['mch_id'] = $this->mch_id;//商户号
  1712. $data['nonce_str'] = $this->createNonceStr(32);//随机字符串
  1713. $data['sign'] = $this->makeSign($data);//签名
  1714. $xml = arr_xml($data);
  1715. $startTimeStamp = milli_time();//请求开始时间
  1716. $response = $this->postXml($xml, $url, false, $timeOut);
  1717. $datas = xml_arr($response);//将xml转为array
  1718. //判断请求结果是否成功
  1719. if($datas['return_code'] != 'SUCCESS'){
  1720. $result = array('status'=>40014,'data'=>$datas);
  1721. return $result;
  1722. }
  1723. //判断签名是否存在,及签名是否正确
  1724. if(!array_key_exists('sign', $datas) ){
  1725. $result = array('status'=>40011,'data'=>'签名错误!');
  1726. return $result;
  1727. }
  1728. $this->reportCostTime($url, $startTimeStamp, $datas);//上报请求花费时间
  1729. //返回结果
  1730. $result = array('status'=>1,'data'=>$datas);
  1731. return $result;
  1732. }
  1733. /**
  1734. * 支付结果通用通知
  1735. * 直接回调函数使用方法: notify(you_function);
  1736. * 回调类成员函数方法:notify(array($this, you_function));
  1737. * $callback 原型为:function function_name($data){}
  1738. * @author bug <3164145970@qq.com>
  1739. * @createtime 2017-09-11 14:41:02
  1740. * @param function $callback
  1741. */
  1742. public function notify(){
  1743. //获取通知的数据
  1744. $xml = file_get_contents('php://input');
  1745. //将xml转为array
  1746. $datas = xml_arr($xml);
  1747. //判断请求结果是否成功
  1748. if($datas['return_code'] != 'SUCCESS'){
  1749. $result = array('status'=>40014,'data'=>$datas['return_msg']);
  1750. return $result;
  1751. }
  1752. //判断业务结果是否成功
  1753. if($datas['result_code'] != 'SUCCESS'){
  1754. $result = array('status'=>40011,'data'=>$datas['err_code_des']);
  1755. return $result;
  1756. }
  1757. //判断签名是否存在
  1758. if(!array_key_exists('sign', $datas)){
  1759. $result = array('status'=>40011,'data'=>'缺少签名参数!');
  1760. return $result;
  1761. }
  1762. //签名验证
  1763. $data = $datas;
  1764. unset($data['sign']);
  1765. if($this->makeSign($data)!=$datas['sign']){
  1766. $result = array('status'=>40011,'data'=>'签名验证失败!');
  1767. return $result;
  1768. }
  1769. //返回结果
  1770. $result = array('status'=>1,'data'=>$datas);
  1771. return $result;
  1772. }
  1773. /**
  1774. * 退款结果通知
  1775. * @author bug <3164145970@qq.com>
  1776. * @createtime 2017-09-22 17:10:21
  1777. * @param array
  1778. */
  1779. public function refund_notify(){
  1780. //获取通知的数据
  1781. $xml = file_get_contents('php://input');
  1782. log_result("//////////// start //////////////");
  1783. log_result($xml);
  1784. //将xml转为array
  1785. $datas = xml_arr($xml);
  1786. log_result("datas:".json_encode($datas));
  1787. //判断请求结果是否成功
  1788. if($datas['return_code'] != 'SUCCESS'){
  1789. $result = array('status'=>40014,'data'=>$datas['return_msg']);
  1790. log_result($datas['return_code'] != 'SUCCESS');
  1791. return $result;
  1792. }
  1793. //对加密字符串进行解密
  1794. $req_info = base64_decode($datas['req_info']);//对加密串A做base64解码,得到加密串B
  1795. log_result("req_info:".$req_info);
  1796. $md5_key = md5($this->key);//对商户key做md5,得到32位小写key
  1797. log_result("md5_key:".$md5_key);
  1798. $info = aes_decode($req_info,$md5_key);//用key*对加密串B做AES-256-ECB解密
  1799. log_result("info:".$info);
  1800. $datas = array_merge($datas,$info);//合并数组 返回结果
  1801. log_result("//////////// end //////////////");
  1802. //返回结果
  1803. $result = array('status'=>1,'data'=>$datas);
  1804. return $result;
  1805. }
  1806. /**
  1807. * 共享收货地址js函数需要的参数
  1808. * @author bug <3164145970@qq.com>
  1809. * @createtime 2017-09-11 16:37:27
  1810. * @param
  1811. * @return 获取共享收货地址js函数需要的参数,json格式可以直接做参数使用
  1812. */
  1813. public function editAddressParameters(){
  1814. $data = array();
  1815. $data["appid"] = $this->appid;
  1816. $data["url"] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  1817. $time = time();
  1818. $data["timestamp"] = "$time";
  1819. $data["noncestr"] = "1234568";
  1820. $data["accesstoken"] = $this->access_token(false);
  1821. ksort($data);
  1822. $params = $this->toUrlParams($data);
  1823. $addrSign = sha1($params);
  1824. $afterData = array(
  1825. "addrSign" => $addrSign,
  1826. "signType" => "sha1",
  1827. "scope" => "jsapi_address",
  1828. "appId" => $this->appid,
  1829. "timeStamp" => $data["timestamp"],
  1830. "nonceStr" => $data["noncestr"]
  1831. );
  1832. $parameters = json_encode($afterData);
  1833. return $parameters;
  1834. }
  1835. /**
  1836. * 生成扫描支付URL,模式一
  1837. * @author bug <3164145970@qq.com>
  1838. * @createtime 2017-09-16 10:40:10
  1839. * @param $productId 产品编号
  1840. * @return [type] [description]
  1841. */
  1842. public function getPrePayUrl($productId)
  1843. {
  1844. $data['product_id'] = $productId;
  1845. $result = $this->bizpayurl($data);
  1846. if($result['status']!=1){
  1847. return $result;
  1848. }
  1849. $url = "weixin://wxpay/bizpayurl?" . $this->toUrlParams($result['data'],true);
  1850. $result['data'] = $url;
  1851. return $result;
  1852. }
  1853. /**
  1854. * 生成二维码
  1855. * @author bug <3164145970@qq.com>
  1856. * @createtime 2017-09-16 11:15:17
  1857. * @param $data 参数集
  1858. * @return [type] [description]
  1859. */
  1860. public function qrcode($data){
  1861. error_reporting(E_ERROR);
  1862. require_once 'phpqrcode/phpqrcode.php';
  1863. $url = urldecode($data);
  1864. header('Content-Type: image/png');
  1865. ob_clean();
  1866. $errorCorrectionLevel = "L"; // 纠错级别:L、M、Q、H
  1867. $matrixPointSize = "4"; //生成图片大小 :1到10
  1868. \QRcode::png($url, false, $errorCorrectionLevel, $matrixPointSize);
  1869. exit();
  1870. }
  1871. /**
  1872. * 格式化参数格式化成url参数
  1873. * @author bug <3164145970@qq.com>
  1874. * @createtime 2017-09-11 09:58:58
  1875. * @param $data 参数集
  1876. * @param $sign 是否考虑sign
  1877. * @return
  1878. */
  1879. private function toUrlParams($data,$sign=false)
  1880. {
  1881. $buff = "";
  1882. foreach ($data as $k => $v)
  1883. {
  1884. if($sign && $v != "" && !is_array($v)){
  1885. $buff .= $k . "=" . $v . "&";
  1886. }else{
  1887. if($k != "sign" && $v != "" && !is_array($v)){
  1888. $buff .= $k . "=" . $v . "&";
  1889. }
  1890. }
  1891. }
  1892. $buff = trim($buff, "&");
  1893. return $buff;
  1894. }
  1895. /**
  1896. * 生成签名
  1897. * @author bug <3164145970@qq.com>
  1898. * @createtime 2017-09-11 10:01:14
  1899. * @param
  1900. * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
  1901. */
  1902. public function makeSign($data)
  1903. {
  1904. //签名步骤一:按字典序排序参数
  1905. ksort($data);
  1906. $string = $this->toUrlParams($data);
  1907. //签名步骤二:在string后加入KEY
  1908. $string = $string . "&key=".$this->key;
  1909. //签名步骤三:MD5加密
  1910. $string = md5($string);
  1911. //签名步骤四:所有字符转为大写
  1912. $result = strtoupper($string);
  1913. return $result;
  1914. }
  1915. /**
  1916. * 以post方式提交xml到对应的接口url
  1917. * @author bug <3164145970@qq.com>
  1918. * @createtime 2017-09-11 10:08:11
  1919. * @param string $xml 需要post的xml数据
  1920. * @param string $url url
  1921. * @param bool $useCert 是否需要证书,默认不需要
  1922. * @param int $second url执行超时时间,默认30s
  1923. * @return [type] [description]
  1924. */
  1925. private function postXml($xml, $url, $useCert = false, $second = 30)
  1926. {
  1927. header("Content-type: text/html; charset=utf-8");
  1928. $ch = curl_init();
  1929. curl_setopt($ch, CURLOPT_TIMEOUT, $second);
  1930. curl_setopt($ch, CURLOPT_URL, $url);
  1931. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  1932. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  1933. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  1934. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
  1935. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  1936. curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
  1937. curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  1938. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  1939. //如果有配置代理这里就设置代理
  1940. if(self::CURL_PROXY_HOST != "0.0.0.0" && self::CURL_PROXY_PORT != 0){
  1941. curl_setopt($ch,CURLOPT_PROXY, self::CURL_PROXY_HOST);
  1942. curl_setopt($ch,CURLOPT_PROXYPORT, self::CURL_PROXY_PORT);
  1943. }
  1944. if($useCert == true){
  1945. //设置证书
  1946. //使用证书:cert 与 key 分别属于两个.pem文件
  1947. curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
  1948. curl_setopt($ch,CURLOPT_SSLCERT, dirname(__FILE__).self::SSLCERT_PATH);
  1949. curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
  1950. curl_setopt($ch,CURLOPT_SSLKEY, dirname(__FILE__).self::SSLKEY_PATH);
  1951. }
  1952. $data = curl_exec($ch);
  1953. if (curl_errno($ch)) {
  1954. return curl_error($ch);
  1955. }
  1956. curl_close($ch);
  1957. return $data;
  1958. // $ch = curl_init();
  1959. // //设置超时
  1960. // curl_setopt($ch, CURLOPT_TIMEOUT, $second);
  1961. // //如果有配置代理这里就设置代理
  1962. // if(self::CURL_PROXY_HOST != "0.0.0.0" && self::CURL_PROXY_PORT != 0){
  1963. // curl_setopt($ch,CURLOPT_PROXY, self::CURL_PROXY_HOST);
  1964. // curl_setopt($ch,CURLOPT_PROXYPORT, self::CURL_PROXY_PORT);
  1965. // }
  1966. // curl_setopt($ch,CURLOPT_URL, $url);
  1967. // curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
  1968. // curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
  1969. // //设置header
  1970. // curl_setopt($ch, CURLOPT_HEADER, FALSE);
  1971. // //要求结果为字符串且输出到屏幕上
  1972. // curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  1973. // if($useCert == true){
  1974. // //设置证书
  1975. // //使用证书:cert 与 key 分别属于两个.pem文件
  1976. // curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
  1977. // curl_setopt($ch,CURLOPT_SSLCERT, dirname(__FILE__).self::SSLCERT_PATH);
  1978. // curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
  1979. // curl_setopt($ch,CURLOPT_SSLKEY, dirname(__FILE__).self::SSLKEY_PATH);
  1980. // }
  1981. // //post提交方式
  1982. // curl_setopt($ch, CURLOPT_POST, TRUE);
  1983. // curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  1984. //运行curl
  1985. // $data = curl_exec($ch);
  1986. //返回结果
  1987. // if($data){
  1988. // curl_close($ch);
  1989. // return $data;
  1990. // } else {
  1991. // $error = curl_errno($ch);
  1992. // curl_close($ch);
  1993. // return $error;
  1994. // }
  1995. }
  1996. /**
  1997. * 上报数据, 上报的时候将屏蔽所有异常流程
  1998. * @author bug <3164145970@qq.com>
  1999. * @createtime 2017-09-11 11:10:20
  2000. * @param string $usrl
  2001. * @param int $startTimeStamp
  2002. * @param array $data
  2003. * @return [type] [description]
  2004. */
  2005. private function reportCostTime($url, $startTimeStamp, $data)
  2006. {
  2007. //如果不需要上报数据
  2008. if(self::REPORT_LEVENL == 0){
  2009. return;
  2010. }
  2011. //如果仅失败上报
  2012. if(self::REPORT_LEVENL == 1 &&
  2013. array_key_exists("return_code", $data) &&
  2014. $data["return_code"] == "SUCCESS" &&
  2015. array_key_exists("result_code", $data) &&
  2016. $data["result_code"] == "SUCCESS")
  2017. {
  2018. return;
  2019. }
  2020. //上报逻辑
  2021. $endTimeStamp = milli_time();
  2022. $result['interface_url'] = $url;
  2023. $result['execute_time_'] = $endTimeStamp - $startTimeStamp;
  2024. //返回状态码
  2025. if(array_key_exists("return_code", $data)){
  2026. $result['return_code'] = $data["return_code"];
  2027. }
  2028. //返回信息
  2029. if(array_key_exists("return_msg", $data)){
  2030. $result['return_msg'] = $data["return_msg"];
  2031. }
  2032. //业务结果
  2033. if(array_key_exists("result_code", $data)){
  2034. $result['result_code'] = $data["result_code"];
  2035. }
  2036. //错误代码
  2037. if(array_key_exists("err_code", $data)){
  2038. $result['err_code'] = $data["err_code"];
  2039. }
  2040. //错误代码描述
  2041. if(array_key_exists("err_code_des", $data)){
  2042. $result['err_code_des'] = $data["err_code_des"];
  2043. }
  2044. //商户订单号
  2045. if(array_key_exists("out_trade_no", $data)){
  2046. $result['out_trade_no'] = $data["out_trade_no"];
  2047. }
  2048. //设备号
  2049. if(array_key_exists("device_info", $data)){
  2050. $result['device_info'] = $data["device_info"];
  2051. }
  2052. try{
  2053. $this->report($result);
  2054. } catch (Exception $e){
  2055. //不做任何处理
  2056. }
  2057. }
  2058. /**********************微信支付 结束********/
  2059. /**********************微信卡券 开始********/
  2060. /**
  2061. * 微信卡券获取api_ticket
  2062. * @author bug <3164145970@qq.com>
  2063. * @createtime 2017-10-17 13:30:13
  2064. * @return api_ticket string 微信卡券调用凭证
  2065. */
  2066. private function api_ticket() {
  2067. // api_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
  2068. $data = json_decode(file_get_contents(dirname(__FILE__)."/json/api_ticket.json"));
  2069. if ($data->expire_time < time()) {
  2070. $access_token = $this->access_token(false);
  2071. if($access_token['status']!=1 && $access_token['status']!=2){
  2072. return $access_token;
  2073. }
  2074. $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card&access_token=".$access_token['data'];
  2075. $res = json_decode(https_get($url));
  2076. if(!isset($res->ticket)){
  2077. $access_token = $this->access_token(true);
  2078. $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card&access_token=".$access_token['data'];
  2079. $res = json_decode(https_get($url));
  2080. }
  2081. $ticket = $res->ticket;
  2082. if ($ticket) {
  2083. $data->expire_time = time() + 7200;
  2084. $data->ticket = $ticket;
  2085. $fp = fopen(dirname(__FILE__)."/json/api_ticket.json", "w");
  2086. fwrite($fp, json_encode($data));
  2087. fclose($fp);
  2088. }
  2089. } else {
  2090. $ticket = $data->ticket;
  2091. }
  2092. return $ticket;
  2093. }
  2094. /**
  2095. * 卡券签名
  2096. * @author bug <3164145970@qq.com>
  2097. * @createtime 2017-10-17 16:43:44
  2098. * @param
  2099. * @return [type] [description]
  2100. */
  2101. public function card_sign($card_id){
  2102. $api_ticket = $this->api_ticket();
  2103. $timestamp = time();
  2104. $nonce_str = $this->createNonceStr();
  2105. $arr = array($api_ticket,$timestamp,$nonce_str,$card_id);
  2106. sort($arr, SORT_STRING);
  2107. $signature = sha1(implode($arr));
  2108. $signPackage = array(
  2109. "timestamp" => $timestamp,
  2110. "nonce_str" => $nonce_str,
  2111. "signature" => $signature,
  2112. );
  2113. return $signPackage;
  2114. }
  2115. /**
  2116. * 查看卡券详情
  2117. * @author bug <3164145970@qq.com>
  2118. * @createtime 2017-10-17 13:59:51
  2119. * @param post_data 请求数据 卡券ID
  2120. * @return json 请求结果
  2121. */
  2122. public function get_card($post_data){
  2123. //获取access_token
  2124. $access_token= $this->access_token(false);
  2125. if($access_token['status']!=1 && $access_token['status']!=2){
  2126. return $access_token;
  2127. }
  2128. //配置请求url,加入access_token参数
  2129. $url = 'https://api.weixin.qq.com/card/get?access_token='.$access_token['data'];
  2130. //将json数组转换成字符串数组
  2131. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  2132. //获取请求结果,并将请求结果转换成json
  2133. $data = json_decode(https_request($url,$post_data),true);
  2134. //access_token 过期重新获取并重新回调当前函数
  2135. if($data['errcode']==42001 || $data['errcode']==40001){
  2136. $access_token = $this->access_token(true);
  2137. return $this->get_card($post_data);
  2138. }
  2139. //返回结果
  2140. if($data['errcode']==0&&$data['errmsg']=='ok'){
  2141. $result = array('status'=>1,'data'=>$data);
  2142. return $result;
  2143. }
  2144. $result = array('status'=>40014,'data'=>$data);
  2145. return $result;
  2146. }
  2147. /**
  2148. * 批量查询卡券列表
  2149. * @author bug <3164145970@qq.com>
  2150. * @createtime 2017-10-17 14:02:10
  2151. * @param post_data 请求数据
  2152. * offset 查询卡列表的起始偏移量,从0开始,即offset: 5是指从从列表里的第六个开始读取。
  2153. * count 需要查询的卡片的数量(数量最大50)。
  2154. * status_list 支持开发者拉出指定状态的卡券列表“CARD_STATUS_NOT_VERIFY”,待审核;“CARD_STATUS_VERIFY_FAIL”,审核失败;“CARD_STATUS_VERIFY_OK”,通过审核;“CARD_STATUS_DELETE”,卡券被商户删除;“CARD_STATUS_DISPATCH”,在公众平台投放过的卡券;
  2155. * @return json 请求结果
  2156. */
  2157. public function card_list($post_data){
  2158. //获取access_token
  2159. $access_token= $this->access_token(false);
  2160. if($access_token['status']!=1 && $access_token['status']!=2){
  2161. return $access_token;
  2162. }
  2163. //配置请求url,加入access_token参数
  2164. $url = 'https://api.weixin.qq.com/card/batchget?access_token='.$access_token['data'];
  2165. //将json数组转换成字符串数组
  2166. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  2167. //获取请求结果,并将请求结果转换成json
  2168. $data = json_decode(https_request($url,$post_data),true);
  2169. //access_token 过期重新获取并重新回调当前函数
  2170. if($data['errcode']==42001 || $data['errcode']==40001){
  2171. $access_token = $this->access_token(true);
  2172. return $this->get_card($card_id);
  2173. }
  2174. //返回结果
  2175. if($data['errcode']==0&&$data['errmsg']=='ok'){
  2176. $result = array('status'=>1,'data'=>$data);
  2177. return $result;
  2178. }
  2179. $result = array('status'=>40014,'data'=>$data);
  2180. return $result;
  2181. }
  2182. /**************************微信会员卡 开始****************************/
  2183. /**
  2184. * 拉取会员信息(积分查询)接口
  2185. * @author bug <3164145970@qq.com>
  2186. * @createtime 2017-10-27 09:24:15
  2187. * @param card_id 查询会员卡的cardid
  2188. * @param code 所查询用户领取到的code值
  2189. * @return [type] [description]
  2190. */
  2191. public function membercard_info($post_data){
  2192. //获取access_token
  2193. $access_token= $this->access_token(false);
  2194. if($access_token['status']!=1 && $access_token['status']!=2){
  2195. return $access_token;
  2196. }
  2197. //配置请求url,加入access_token参数
  2198. $url = 'https://api.weixin.qq.com/card/membercard/userinfo/get?access_token='.$access_token['data'];
  2199. //将json数组转换成字符串数组
  2200. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  2201. //获取请求结果,并将请求结果转换成json
  2202. $data = json_decode(https_request($url,$post_data),true);
  2203. //access_token 过期重新获取并重新回调当前函数
  2204. if($data['errcode']==42001 || $data['errcode']==40001){
  2205. $access_token = $this->access_token(true);
  2206. return $this->membercard_info($post_data);
  2207. }
  2208. //返回结果
  2209. if($data['errcode']==0&&$data['errmsg']=='ok'){
  2210. $result = array('status'=>1,'data'=>$data);
  2211. return $result;
  2212. }
  2213. $result = array('status'=>40014,'data'=>$data);
  2214. return $result;
  2215. }
  2216. /**
  2217. * 更新会员信息
  2218. * @author bug <3164145970@qq.com>
  2219. * @createtime 2017-10-27 15:08:46
  2220. * @param
  2221. * @return [type] [description]
  2222. */
  2223. public function membercard_update($post_data){
  2224. //获取access_token
  2225. $access_token= $this->access_token(false);
  2226. if($access_token['status']!=1 && $access_token['status']!=2){
  2227. return $access_token;
  2228. }
  2229. //配置请求url,加入access_token参数
  2230. $url = 'https://api.weixin.qq.com/card/membercard/updateuser?access_token='.$access_token['data'];
  2231. //将json数组转换成字符串数组
  2232. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  2233. //获取请求结果,并将请求结果转换成json
  2234. $data = json_decode(https_request($url,$post_data),true);
  2235. //access_token 过期重新获取并重新回调当前函数
  2236. if($data['errcode']==42001 || $data['errcode']==40001){
  2237. $access_token = $this->access_token(true);
  2238. return $this->membercard_update($post_data);
  2239. }
  2240. //返回结果
  2241. if($data['errcode']==0&&$data['errmsg']=='ok'){
  2242. $result = array('status'=>1,'data'=>$data);
  2243. return $result;
  2244. }
  2245. $result = array('status'=>40014,'data'=>$data);
  2246. return $result;
  2247. }
  2248. /**
  2249. * 激活会员卡
  2250. * @author bug <3164145970@qq.com>
  2251. * @createtime 2017-10-27 11:45:44
  2252. * @param
  2253. * @return [type] [description]
  2254. */
  2255. public function membercard_active($post_data){
  2256. //获取access_token
  2257. $access_token= $this->access_token(false);
  2258. if($access_token['status']!=1 && $access_token['status']!=2){
  2259. return $access_token;
  2260. }
  2261. //配置请求url,加入access_token参数
  2262. $url = 'https://api.weixin.qq.com/card/membercard/activate?access_token='.$access_token['data'];
  2263. //将json数组转换成字符串数组
  2264. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  2265. //获取请求结果,并将请求结果转换成json
  2266. $data = json_decode(https_request($url,$post_data),true);
  2267. //access_token 过期重新获取并重新回调当前函数
  2268. if($data['errcode']==42001 || $data['errcode']==40001){
  2269. $access_token = $this->access_token(true);
  2270. return $this->membercard_active($post_data);
  2271. }
  2272. //返回结果
  2273. if($data['errcode']==0&&$data['errmsg']=='ok'){
  2274. $result = array('status'=>1,'data'=>$data);
  2275. return $result;
  2276. }
  2277. $result = array('status'=>40014,'data'=>$data);
  2278. return $result;
  2279. }
  2280. /**
  2281. * 设置开卡字段接口
  2282. * @author bug <3164145970@qq.com>
  2283. * @createtime 2017-10-27 13:54:02
  2284. * @param
  2285. * @return [type] [description]
  2286. */
  2287. public function activateuserform($post_data){
  2288. //获取access_token
  2289. $access_token= $this->access_token(false);
  2290. if($access_token['status']!=1 && $access_token['status']!=2){
  2291. return $access_token;
  2292. }
  2293. //配置请求url,加入access_token参数
  2294. $url = 'https://api.weixin.qq.com/card/membercard/activateuserform/set?access_token='.$access_token['data'];
  2295. //将json数组转换成字符串数组
  2296. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  2297. //获取请求结果,并将请求结果转换成json
  2298. $data = json_decode(https_request($url,$post_data),true);
  2299. //access_token 过期重新获取并重新回调当前函数
  2300. if($data['errcode']==42001 || $data['errcode']==40001){
  2301. $access_token = $this->access_token(true);
  2302. return $this->activateuserform($post_data);
  2303. }
  2304. //返回结果
  2305. if($data['errcode']==0&&$data['errmsg']=='ok'){
  2306. $result = array('status'=>1,'data'=>$data);
  2307. return $result;
  2308. }
  2309. $result = array('status'=>40014,'data'=>$data);
  2310. return $result;
  2311. }
  2312. /**
  2313. * 更改会员卡信息接口
  2314. * @author bug <3164145970@qq.com>
  2315. * @createtime 2017-10-27 09:36:18
  2316. * @param 提交修改的数据集
  2317. * @return [type] [description]
  2318. */
  2319. public function card_update($post_data){
  2320. //获取access_token
  2321. $access_token= $this->access_token(false);
  2322. if($access_token['status']!=1 && $access_token['status']!=2){
  2323. return $access_token;
  2324. }
  2325. //配置请求url,加入access_token参数
  2326. $url = 'https://api.weixin.qq.com/card/update?access_token='.$access_token['data'];
  2327. //将json数组转换成字符串数组
  2328. $post_data = json_encode($post_data,JSON_UNESCAPED_UNICODE);
  2329. //获取请求结果,并将请求结果转换成json
  2330. $data = json_decode(https_request($url,$post_data),true);
  2331. //access_token 过期重新获取并重新回调当前函数
  2332. if($data['errcode']==42001 || $data['errcode']==40001){
  2333. $access_token = $this->access_token(true);
  2334. return $this->card_update($post_data);
  2335. }
  2336. //返回结果
  2337. if($data['errcode']==0&&$data['errmsg']=='ok'){
  2338. $result = array('status'=>1,'data'=>$data);
  2339. return $result;
  2340. }
  2341. $result = array('status'=>40014,'data'=>$data);
  2342. return $result;
  2343. }
  2344. /**************************微信会员卡 结束****************************/
  2345. /**********************微信卡券 结束********/
  2346. }
  2347. ?>
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post