weixin.account.class.php 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739
  1. <?php
  2. /**
  3. * [WeEngine System] Copyright (c) 2014 WE7.CC
  4. * WeEngine is NOT a free software, it under the license terms, visited http://www.we7.cc/ for more details.
  5. */
  6. defined('IN_IA') or exit('Access Denied');
  7. class WeixinAccount extends WeAccount {
  8. protected $tablename = 'account_wechats';
  9. protected $menuFrame = 'account';
  10. protected $type = ACCOUNT_TYPE_OFFCIAL_NORMAL;
  11. protected $typeName = '公众号';
  12. protected $typeSign = ACCOUNT_TYPE_SIGN;
  13. public $types = array(
  14. 'view', 'click', 'scancode_push',
  15. 'scancode_waitmsg', 'pic_sysphoto', 'pic_photo_or_album',
  16. 'pic_weixin', 'location_select', 'media_id', 'view_limited'
  17. );
  18. protected function getAccountInfo($acid) {
  19. $account = table('account')->getWechatappAccount($acid);
  20. $account['encrypt_key'] = $account['key'];
  21. return $account;
  22. }
  23. public function checkSign() {
  24. $token = $this->account['token'];
  25. $signkey = array($token, $_GET['timestamp'], $_GET['nonce']);
  26. sort($signkey, SORT_STRING);
  27. $signString = implode($signkey);
  28. $signString = sha1($signString);
  29. return $signString == $_GET['signature'];
  30. }
  31. public function checkSignature($encrypt_msg) {
  32. $str = $this->buildSignature($encrypt_msg);
  33. return $str == $_GET['msg_signature'];
  34. }
  35. public function checkIntoManage() {
  36. if (empty($this->account) || (!empty($this->account['account']) && !in_array($this->account['type'], array(ACCOUNT_TYPE_OFFCIAL_NORMAL, ACCOUNT_TYPE_OFFCIAL_AUTH)) && !defined('IN_MODULE'))) {
  37. return false;
  38. }
  39. return true;
  40. }
  41. public function local_checkSignature($packet) {
  42. $token = $this->account['token'];
  43. $array = array($packet['Encrypt'], $token, $packet['TimeStamp'], $packet['Nonce']);
  44. sort($array, SORT_STRING);
  45. $str = implode($array);
  46. $str = sha1($str);
  47. return $str == $packet['MsgSignature'];
  48. }
  49. public function local_decryptMsg($postData) {
  50. $token = $this->account['token'];
  51. $encodingaeskey = $this->account['encodingaeskey'];
  52. $appid = $this->account['encrypt_key'];
  53. if(strlen($encodingaeskey) != 43) {
  54. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40004 \n,错误描述为: " . $this->encryptErrorCode('40004'));
  55. }
  56. $key = base64_decode($encodingaeskey . '=');
  57. $packet = $this->local_xmlExtract($postData);
  58. if(is_error($packet)) {
  59. return error(-1, $packet['message']);
  60. }
  61. $istrue = $this->local_checkSignature($packet);
  62. if(!$istrue) {
  63. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40001 \n,错误描述为: " . $this->encryptErrorCode('40001'));
  64. }
  65. $ciphertext_dec = base64_decode($packet['Encrypt']);
  66. $iv = substr($key, 0, 16);
  67. $decrypted = openssl_decrypt($ciphertext_dec, 'AES-256-CBC', $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
  68. $block_size = 32;
  69. $pad = ord(substr($decrypted, -1));
  70. if ($pad < 1 || $pad > 32) {
  71. $pad = 0;
  72. }
  73. $result = substr($decrypted, 0, (strlen($decrypted) - $pad));
  74. if (strlen($result) < 16) {
  75. return '';
  76. }
  77. $content = substr($result, 16, strlen($result));
  78. $len_list = unpack("N", substr($content, 0, 4));
  79. $xml_len = $len_list[1];
  80. $xml_content = substr($content, 4, $xml_len);
  81. $from_appid = substr($content, $xml_len + 4);
  82. if ($from_appid != $appid) {
  83. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40005 \n,错误描述为: " . $this->encryptErrorCode('40005'));
  84. }
  85. return $xml_content;
  86. }
  87. public function buildSignature($encrypt_msg) {
  88. $token = $this->account['token'];
  89. $array = array($encrypt_msg, $token, $_GET['timestamp'], $_GET['nonce']);
  90. sort($array, SORT_STRING);
  91. $str = implode($array);
  92. $str = sha1($str);
  93. return $str;
  94. }
  95. public function encryptMsg($text) {
  96. $token = $this->account['token'];
  97. $encodingaeskey = $this->account['encodingaeskey'];
  98. $appid = $this->account['encrypt_key'];
  99. $key = base64_decode($encodingaeskey . '=');
  100. $text = random(16) . pack("N", strlen($text)) . $text . $appid;
  101. $iv = substr($key, 0, 16);
  102. $block_size = 32;
  103. $text_length = strlen($text);
  104. $amount_to_pad = $block_size - ($text_length % $block_size);
  105. if ($amount_to_pad == 0) {
  106. $amount_to_pad = $block_size;
  107. }
  108. $pad_chr = chr($amount_to_pad);
  109. $tmp = '';
  110. for ($index = 0; $index < $amount_to_pad; $index++) {
  111. $tmp .= $pad_chr;
  112. }
  113. $text = $text . $tmp;
  114. $encrypted = openssl_encrypt($text, 'AES-256-CBC', $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
  115. $encrypt_msg = base64_encode($encrypted);
  116. $signature = $this->buildSignature($encrypt_msg);
  117. return array($signature, $encrypt_msg);
  118. }
  119. public function decryptMsg($postData) {
  120. $token = $this->account['token'];
  121. $encodingaeskey = $this->account['encodingaeskey'];
  122. $appid = $this->account['encrypt_key'];
  123. $key = base64_decode($encodingaeskey . '=');
  124. if(strlen($encodingaeskey) != 43) {
  125. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40004 \n,错误描述为: " . $this->encryptErrorCode('40004'));
  126. }
  127. $packet = $this->xmlExtract($postData);
  128. if(is_error($packet)) {
  129. return error(-1, $packet['message']);
  130. }
  131. $istrue = $this->checkSignature($packet['encrypt']);
  132. if(!$istrue) {
  133. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40001 \n,错误描述为: " . $this->encryptErrorCode('40001'));
  134. }
  135. $ciphertext_dec = base64_decode($packet['encrypt']);
  136. $iv = substr($key, 0, 16);
  137. $decrypted = openssl_decrypt($ciphertext_dec, 'AES-256-CBC', $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
  138. $pad = ord(substr($decrypted, -1));
  139. if ($pad < 1 || $pad > 32) {
  140. $pad = 0;
  141. }
  142. $result = substr($decrypted, 0, (strlen($decrypted) - $pad));
  143. if (strlen($result) < 16) {
  144. return '';
  145. }
  146. $content = substr($result, 16, strlen($result));
  147. $len_list = unpack("N", substr($content, 0, 4));
  148. $xml_len = $len_list[1];
  149. $xml_content = substr($content, 4, $xml_len);
  150. $from_appid = substr($content, $xml_len + 4);
  151. if ($from_appid != $appid) {
  152. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40005 \n,错误描述为: " . $this->encryptErrorCode('40005'));
  153. }
  154. return $xml_content;
  155. }
  156. function xmlDetract($data) {
  157. $xml['Encrypt'] = $data[1];
  158. $xml['MsgSignature'] = $data[0];
  159. $xml['TimeStamp'] = $_GET['timestamp'];
  160. $xml['Nonce'] = $_GET['nonce'];
  161. return array2xml($xml);
  162. }
  163. public function xmlExtract($message) {
  164. $packet = array();
  165. if (!empty($message)){
  166. $obj = isimplexml_load_string($message, 'SimpleXMLElement', LIBXML_NOCDATA);
  167. if($obj instanceof SimpleXMLElement) {
  168. $packet['encrypt'] = strval($obj->Encrypt);
  169. $packet['to'] = strval($obj->ToUserName);
  170. }
  171. }
  172. if(!empty($packet['encrypt'])) {
  173. return $packet;
  174. } else {
  175. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40002 \n,错误描述为: " . $this->encryptErrorCode('40002'));
  176. }
  177. }
  178. public function local_xmlExtract($message) {
  179. $packet = array();
  180. if (!empty($message)){
  181. $obj = isimplexml_load_string($message, 'SimpleXMLElement', LIBXML_NOCDATA);
  182. if($obj instanceof SimpleXMLElement) {
  183. $packet['Encrypt'] = strval($obj->Encrypt);
  184. $packet['MsgSignature'] = strval($obj->MsgSignature);
  185. $packet['TimeStamp'] = strval($obj->TimeStamp);
  186. $packet['Nonce'] = strval($obj->Nonce);
  187. }
  188. }
  189. if(!empty($packet)) {
  190. return $packet;
  191. } else {
  192. return error(-1, "微信公众平台返回接口错误. \n错误代码为: 40002 \n,错误描述为: " . $this->encryptErrorCode('40002'));
  193. }
  194. }
  195. public function queryAvailableMessages() {
  196. $messages = array('text', 'image', 'voice', 'video', 'location', 'link', 'subscribe', 'unsubscribe');
  197. if(!empty($this->account['key']) && !empty($this->account['secret'])) {
  198. $level = intval($this->account['level']);
  199. if($level > 1){
  200. $messages[] = 'click';
  201. $messages[] = 'view';
  202. }
  203. if ($level > 2) {
  204. $messages[] = 'qr';
  205. $messages[] = 'trace';
  206. }
  207. }
  208. return $messages;
  209. }
  210. public function queryAvailablePackets() {
  211. $packets = array('text', 'music', 'news');
  212. if(!empty($this->account['key']) && !empty($this->account['secret'])) {
  213. if (intval($this->account['level']) > 1) {
  214. $packets[] = 'image';
  215. $packets[] = 'voice';
  216. $packets[] = 'video';
  217. }
  218. }
  219. return $packets;
  220. }
  221. public function isMenuSupported() {
  222. return !empty($this->account['key']) &&
  223. !empty($this->account['secret']) &&
  224. (intval($this->account['level']) > 1);
  225. }
  226. public function menuCreate($menu) {
  227. global $_W;
  228. $token = $this->getAccessToken();
  229. if(is_error($token)){
  230. return $token;
  231. }
  232. $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={$token}";
  233. if(!empty($menu['matchrule'])) {
  234. $url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token={$token}";
  235. }
  236. $data = urldecode(json_encode($menu));
  237. $response = ihttp_post($url, $data);
  238. if(is_error($response)) {
  239. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  240. }
  241. $result = @json_decode($response['content'], true);
  242. if(!empty($result['errcode'])) {
  243. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  244. }
  245. return $result['menuid'];
  246. }
  247. public function menuBuild($data_array, $is_conditional = false) {
  248. $menu = array();
  249. if (empty($data_array) || empty($data_array['button']) || !is_array($data_array)) {
  250. return $menu;
  251. }
  252. foreach ($data_array['button'] as $button) {
  253. $temp = array();
  254. $temp['name'] = preg_replace_callback('/\:\:([0-9a-zA-Z_-]+)\:\:/', create_function('$matches', 'return utf8_bytes(hexdec($matches[1]));'), $button['name']);
  255. $temp['name'] = urlencode($temp['name']);
  256. if (empty($button['sub_button'])) {
  257. $temp['type'] = $button['type'];
  258. if ($button['type'] == 'view') {
  259. $temp['url'] = urlencode($button['url']);
  260. } elseif ($button['type'] == 'click') {
  261. if (!empty($button['media_id']) && empty($button['key'])) {
  262. $temp['media_id'] = urlencode($button['media_id']);
  263. $temp['type'] = 'media_id';
  264. } elseif (empty($button['media_id']) && !empty($button['key'])) {
  265. $temp['type'] = 'click';
  266. $temp['key'] = urlencode($button['key']);
  267. }
  268. } elseif ($button['type'] == 'media_id' || $button['type'] == 'view_limited') {
  269. $temp['media_id'] = urlencode($button['media_id']);
  270. } elseif ($button['type'] == 'miniprogram') {
  271. $temp['appid'] = trim($button['appid']);
  272. $temp['pagepath'] = urlencode($button['pagepath']);
  273. $temp['url'] = urlencode($button['url']);
  274. } else {
  275. $temp['key'] = urlencode($button['key']);
  276. }
  277. } else {
  278. foreach ($button['sub_button'] as $sub_button) {
  279. $sub_temp = array();
  280. $sub_temp['name'] = preg_replace_callback('/\:\:([0-9a-zA-Z_-]+)\:\:/', create_function('$matches', 'return utf8_bytes(hexdec($matches[1]));'), $sub_button['name']);
  281. $sub_temp['name'] = urlencode($sub_temp['name']);
  282. $sub_temp['type'] = $sub_button['type'];
  283. if ($sub_button['type'] == 'view') {
  284. $sub_temp['url'] = urlencode($sub_button['url']);
  285. } elseif ($sub_button['type'] == 'click') {
  286. if (!empty($sub_button['media_id']) && empty($sub_button['key'])) {
  287. $sub_temp['media_id'] = urlencode($sub_button['media_id']);
  288. $sub_temp['type'] = 'media_id';
  289. } elseif (empty($sub_button['media_id']) && !empty($sub_button['key'])) {
  290. $sub_temp['type'] = 'click';
  291. $sub_temp['key'] = urlencode($sub_button['key']);
  292. }
  293. } elseif ($sub_button['type'] == 'media_id' || $sub_button['type'] == 'view_limited') {
  294. $sub_temp['media_id'] = urlencode($sub_button['media_id']);
  295. } elseif ($sub_button['type'] == 'miniprogram') {
  296. $sub_temp['appid'] = trim($sub_button['appid']);
  297. $sub_temp['pagepath'] = urlencode($sub_button['pagepath']);
  298. $sub_temp['url'] = urlencode($sub_button['url']);
  299. } else {
  300. $sub_temp['key'] = urlencode($sub_button['key']);
  301. }
  302. $temp['sub_button'][] = $sub_temp;
  303. }
  304. }
  305. $menu['button'][] = $temp;
  306. }
  307. if (empty($is_conditional) || empty($data_array['matchrule']) || !is_array($data_array['matchrule'])) {
  308. return $menu;
  309. }
  310. if($data_array['matchrule']['sex'] > 0) {
  311. $menu['matchrule']['sex'] = $data_array['matchrule']['sex'];
  312. }
  313. if($data_array['matchrule']['group_id'] != -1) {
  314. $menu['matchrule']['tag_id'] = $data_array['matchrule']['group_id'];
  315. }
  316. if($data_array['matchrule']['client_platform_type'] > 0) {
  317. $menu['matchrule']['client_platform_type'] = $data_array['matchrule']['client_platform_type'];
  318. }
  319. if(!empty($data_array['matchrule']['province'])) {
  320. $menu['matchrule']['country'] = urlencode('中国');
  321. $menu['matchrule']['province'] = urlencode($data_array['matchrule']['province']);
  322. if(!empty($data_array['matchrule']['city'])) {
  323. $menu['matchrule']['city'] = urlencode($data_array['matchrule']['city']);
  324. }
  325. }
  326. if(!empty($data_array['matchrule']['language'])) {
  327. $inarray = 0;
  328. $languages = menu_languages();
  329. foreach ($languages as $key => $value) {
  330. if(in_array($data_array['matchrule']['language'], $value, true)) {
  331. $inarray = 1;
  332. break;
  333. }
  334. }
  335. if($inarray === 1) {
  336. $menu['matchrule']['language'] = $data_array['matchrule']['language'];
  337. }
  338. }
  339. return $menu;
  340. }
  341. public function menuDelete($menuid = 0) {
  342. $token = $this->getAccessToken();
  343. if(is_error($token)){
  344. return $token;
  345. }
  346. if($menuid > 0) {
  347. $url = "https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token={$token}";
  348. $data = array(
  349. 'menuid' => $menuid
  350. );
  351. $response = ihttp_post($url, json_encode($data));
  352. } else {
  353. $url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token={$token}";
  354. $response = ihttp_get($url);
  355. }
  356. if(is_error($response)) {
  357. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  358. }
  359. $result = @json_decode($response['content'], true);
  360. if(!empty($result['errcode'])) {
  361. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  362. }
  363. return true;
  364. }
  365. public function menuModify($menu) {
  366. return $this->menuCreate($menu);
  367. }
  368. public function menuCurrentQuery() {
  369. $token = $this->getAccessToken();
  370. if(is_error($token)){
  371. return $token;
  372. }
  373. $url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token={$token}";
  374. $result = $this->requestApi($url);
  375. return $result;
  376. }
  377. public function menuQuery() {
  378. $token = $this->getAccessToken();
  379. if(is_error($token)){
  380. return $token;
  381. }
  382. $url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token={$token}";
  383. $response = ihttp_get($url);
  384. if(is_error($response)) {
  385. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  386. }
  387. $result = @json_decode($response['content'], true);
  388. if(!empty($result['errcode']) && $result['errcode'] != '46003') {
  389. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  390. }
  391. return $result;
  392. }
  393. public function fansQueryInfo($uniid, $isOpen = true) {
  394. if($isOpen) {
  395. $openid = $uniid;
  396. } else {
  397. exit('error');
  398. }
  399. $token = $this->getAccessToken();
  400. if(is_error($token)){
  401. return $token;
  402. }
  403. $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$token}&openid={$openid}&lang=zh_CN";
  404. $response = ihttp_get($url);
  405. if(is_error($response)) {
  406. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  407. }
  408. preg_match('/city":"(.*)","province":"(.*)","country":"(.*)"/U', $response['content'], $reg_arr);
  409. $city = htmlentities(bin2hex($reg_arr[1]));
  410. $province = htmlentities(bin2hex($reg_arr[2]));
  411. $country = htmlentities(bin2hex($reg_arr[3]));
  412. $response['content'] = str_replace('"city":"'.$reg_arr[1].'","province":"'.$reg_arr[2].'","country":"'.$reg_arr[3].'"', '"city":"'.$city.'","province":"'.$province.'","country":"'.$country.'"', $response['content']);
  413. $result = @json_decode($response['content'], true);
  414. $result['city'] = hex2bin(html_entity_decode($result['city']));
  415. $result['province'] = hex2bin(html_entity_decode($result['province']));
  416. $result['country'] = hex2bin(html_entity_decode($result['country']));
  417. $result['headimgurl'] = str_replace('http:', 'https:', $result['headimgurl']);
  418. unset($result['remark'], $result['subscribe_scene'], $result['qr_scene'], $result['qr_scene_str']);
  419. if(empty($result)) {
  420. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  421. } elseif(!empty($result['errcode'])) {
  422. return error($result['errcode'], "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  423. }
  424. return $result;
  425. }
  426. public function fansBatchQueryInfo($data) {
  427. if(empty($data)) {
  428. return error(-1, '粉丝openid错误');
  429. }
  430. foreach($data as $da) {
  431. $post[] = array(
  432. 'openid' => trim($da),
  433. 'lang' => 'zh-CN'
  434. );
  435. }
  436. $data = array();
  437. $data['user_list'] = $post;
  438. $token = $this->getAccessToken();
  439. if(is_error($token)){
  440. return $token;
  441. }
  442. $url = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token={$token}";
  443. $response = ihttp_post($url, json_encode($data));
  444. if(is_error($response)) {
  445. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  446. }
  447. $result = @json_decode($response['content'], true);
  448. if(empty($result)) {
  449. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  450. } elseif(!empty($result['errcode'])) {
  451. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  452. }
  453. return $result['user_info_list'];
  454. }
  455. public function fansAll($startopenid = '') {
  456. global $_GPC;
  457. $token = $this->getAccessToken();
  458. if(is_error($token)){
  459. return $token;
  460. }
  461. $url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token=' . $token;
  462. if(!empty($_GPC['next_openid'])) {
  463. $startopenid = $_GPC['next_openid'];
  464. }
  465. if (!empty($startopenid)) {
  466. $url .= '&next_openid=' . $startopenid;
  467. }
  468. $response = ihttp_get($url);
  469. if(is_error($response)) {
  470. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  471. }
  472. $result = @json_decode($response['content'], true);
  473. if(empty($result)) {
  474. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  475. } elseif(!empty($result['errcode'])) {
  476. return error(-1, "访问公众平台接口失败, 错误: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  477. }
  478. $return = array();
  479. $return['total'] = $result['total'];
  480. $return['fans'] = $result['data']['openid'];
  481. $return['next'] = $result['next_openid'];
  482. return $return;
  483. }
  484. public function queryBarCodeActions() {
  485. return array('barCodeCreateDisposable', 'barCodeCreateFixed');
  486. }
  487. public function barCodeCreateDisposable($barcode) {
  488. $barcode['expire_seconds'] = empty($barcode['expire_seconds']) ? 2592000 : $barcode['expire_seconds'];
  489. if (empty($barcode['action_info']['scene']['scene_id']) || empty($barcode['action_name'])) {
  490. return error('1', 'Invalid params');
  491. }
  492. $token = $this->getAccessToken();
  493. $response = ihttp_request("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$token, json_encode($barcode));
  494. if (is_error($response)) {
  495. return $response;
  496. }
  497. $content = @json_decode($response['content'], true);
  498. if(empty($content)) {
  499. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  500. }
  501. if (!empty($content['errcode'])) {
  502. return error(-1, "访问微信接口错误, 错误代码: {$content['errcode']}, 错误信息: {$content['errmsg']},错误详情:{$this->errorCode($content['errcode'])}");
  503. }
  504. return $content;
  505. }
  506. public function barCodeCreateFixed($barcode) {
  507. if($barcode['action_name'] == 'QR_LIMIT_SCENE' && empty($barcode['action_info']['scene']['scene_id'])) {
  508. return error('1', '场景值错误');
  509. }
  510. if($barcode['action_name'] == 'QR_LIMIT_STR_SCENE' && empty($barcode['action_info']['scene']['scene_str'])) {
  511. return error('1', '场景字符串错误');
  512. }
  513. $token = $this->getAccessToken();
  514. $response = ihttp_request("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$token, json_encode($barcode));
  515. if (is_error($response)) {
  516. return $response;
  517. }
  518. $content = @json_decode($response['content'], true);
  519. if(empty($content)) {
  520. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  521. }
  522. if(!empty($content['errcode'])) {
  523. return error(-1, "访问微信接口错误, 错误代码: {$content['errcode']}, 错误信息: {$content['errmsg']},错误详情:{$this->errorCode($content['errcode'])}");
  524. }
  525. return $content;
  526. }
  527. private function encryptErrorCode($code) {
  528. $errors = array(
  529. '40001' => '签名验证错误',
  530. '40002' => 'xml解析失败',
  531. '40003' => 'sha加密生成签名失败',
  532. '40004' => 'encodingAesKey 非法',
  533. '40005' => 'appid 校验错误',
  534. '40006' => 'aes 加密失败',
  535. '40007' => 'aes 解密失败',
  536. '40008' => '解密后得到的buffer非法',
  537. '40009' => 'base64加密失败',
  538. '40010' => 'base64解密失败',
  539. '40011' => '生成xml失败',
  540. );
  541. if($errors[$code]) {
  542. return $errors[$code];
  543. } else {
  544. return '未知错误';
  545. }
  546. }
  547. public function changeSend($send) {
  548. if (empty($send)) {
  549. return error(-1, 'Invalid params');
  550. }
  551. $token = $this->getAccessToken();
  552. if(is_error($token)){
  553. return $token;
  554. }
  555. $sendapi = 'https://api.weixin.qq.com/pay/delivernotify?access_token='.$token;
  556. $response = ihttp_request($sendapi, json_encode($send));
  557. $response = json_decode($response['content'], true);
  558. if (empty($response)) {
  559. return error(-1, '发货失败,请检查您的公众号权限或是公众号AppId和公众号AppSecret!');
  560. }
  561. if (!empty($response['errcode'])) {
  562. return error(-1, $response['errmsg']);
  563. }
  564. return true;
  565. }
  566. public function getAccessToken() {
  567. $cachekey = cache_system_key('accesstoken', array('uniacid' => $this->account['uniacid']));
  568. $cache = cache_load($cachekey);
  569. if (!empty($cache) && !empty($cache['token']) && $cache['expire'] > TIMESTAMP) {
  570. $this->account['access_token'] = $cache;
  571. return $cache['token'];
  572. }
  573. if (empty($this->account['key']) || empty($this->account['secret'])) {
  574. return error('-1', '未填写公众号的 appid 或 appsecret!');
  575. }
  576. $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->account['key']}&secret={$this->account['secret']}";
  577. $content = ihttp_get($url);
  578. if(is_error($content)) {
  579. return error('-1', '获取微信公众号授权失败, 请稍后重试!错误详情: ' . $content['message']);
  580. }
  581. if (empty($content['content'])) {
  582. return error('-1', 'AccessToken获取失败,请检查appid和appsecret的值是否与微信公众平台一致!');
  583. }
  584. $token = @json_decode($content['content'], true);
  585. if ($token['errcode'] == '40164') {
  586. return error(-1, $this->errorCode($token['errcode'], $token['errmsg']));
  587. }
  588. if(empty($token) || !is_array($token) || empty($token['access_token']) || empty($token['expires_in'])) {
  589. $errorinfo = substr($content['meta'], strpos($content['meta'], '{'));
  590. $errorinfo = @json_decode($errorinfo, true);
  591. return error('-1', '获取微信公众号授权失败, 请稍后重试! 公众平台返回原始数据为: 错误代码-' . $errorinfo['errcode'] . ',错误信息-' . $errorinfo['errmsg']);
  592. }
  593. $record = array();
  594. $record['token'] = $token['access_token'];
  595. $record['expire'] = TIMESTAMP + $token['expires_in'] - 200;
  596. $this->account['access_token'] = $record;
  597. cache_write($cachekey, $record);
  598. return $record['token'];
  599. }
  600. public function getVailableAccessToken() {
  601. $accounts = pdo_fetchall("SELECT `key`, `secret`, `acid` FROM ".tablename('account_wechats')." WHERE uniacid = :uniacid ORDER BY `level` DESC ", array(':uniacid' => $GLOBALS['_W']['uniacid']));
  602. if (empty($accounts)) {
  603. return error(-1, 'no permission');
  604. }
  605. foreach ($accounts as $account) {
  606. if (empty($account['key']) || empty($account['secret'])) {
  607. continue;
  608. }
  609. $acid = $account['acid'];
  610. break;
  611. }
  612. $account = WeAccount::create($acid);
  613. return $account->getAccessToken();
  614. }
  615. public function fetch_token() {
  616. return $this->getAccessToken();
  617. }
  618. public function fetch_available_token() {
  619. return $this->getVailableAccessToken();
  620. }
  621. public function clearAccessToken() {
  622. $access_token = $this->getAccessToken();
  623. if(is_error($access_token)){
  624. return $access_token;
  625. }
  626. $url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=' . $access_token;
  627. $response = $this->requestApi($url);
  628. if (is_error($response) && $response['errno'] == '40001') {
  629. cache_delete(cache_system_key('accesstoken', array('uniacid' => $this->account['uniacid'])));
  630. }
  631. return true;
  632. }
  633. public function getJsApiTicket(){
  634. $cachekey = cache_system_key('jsticket', array('acid' => $this->account['acid']));
  635. $cache = cache_load($cachekey);
  636. if(!empty($cache) && !empty($cache['ticket']) && $cache['expire'] > TIMESTAMP) {
  637. return $cache['ticket'];
  638. }
  639. $access_token = $this->getAccessToken();
  640. if(is_error($access_token)){
  641. return $access_token;
  642. }
  643. $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$access_token}&type=jsapi";
  644. $content = ihttp_get($url);
  645. if(is_error($content)) {
  646. return error(-1, '调用接口获取微信公众号 jsapi_ticket 失败, 错误信息: ' . $content['message']);
  647. }
  648. $result = @json_decode($content['content'], true);
  649. if(empty($result) || intval(($result['errcode'])) != 0 || $result['errmsg'] != 'ok') {
  650. return error(-1, '获取微信公众号 jsapi_ticket 结果错误, 错误信息: ' . $result['errmsg']);
  651. }
  652. $record = array();
  653. $record['ticket'] = $result['ticket'];
  654. $record['expire'] = TIMESTAMP + $result['expires_in'] - 200;
  655. $this->account['jsapi_ticket'] = $record;
  656. cache_write($cachekey, $record);
  657. return $record['ticket'];
  658. }
  659. public function getJssdkConfig($url = ''){
  660. global $_W;
  661. $jsapiTicket = $this->getJsApiTicket();
  662. if(is_error($jsapiTicket)){
  663. $jsapiTicket = $jsapiTicket['message'];
  664. }
  665. $nonceStr = random(16);
  666. $timestamp = TIMESTAMP;
  667. $url = empty($url) ? $_W['siteurl'] : $url;
  668. $string1 = "jsapi_ticket={$jsapiTicket}&noncestr={$nonceStr}&timestamp={$timestamp}&url={$url}";
  669. $signature = sha1($string1);
  670. $config = array(
  671. "appId" => $this->account['key'],
  672. "nonceStr" => $nonceStr,
  673. "timestamp" => "$timestamp",
  674. "signature" => $signature,
  675. );
  676. if(DEVELOPMENT) {
  677. $config['url'] = $url;
  678. $config['string1'] = $string1;
  679. $config['name'] = $this->account['name'];
  680. }
  681. return $config;
  682. }
  683. public function long2short($longurl) {
  684. $token = $this->getAccessToken();
  685. if(is_error($token)){
  686. return $token;
  687. }
  688. $url = "https://api.weixin.qq.com/cgi-bin/shorturl?access_token={$token}";
  689. $send = array();
  690. $send['action'] = 'long2short';
  691. $send['long_url'] = $longurl;
  692. $response = ihttp_request($url, json_encode($send));
  693. if(is_error($response)) {
  694. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  695. }
  696. $result = @json_decode($response['content'], true);
  697. if(empty($result)) {
  698. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  699. } elseif(!empty($result['errcode'])) {
  700. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  701. }
  702. return $result;
  703. }
  704. public function fetchChatLog($params = array()) {
  705. if(empty($params['starttime']) || empty($params['endtime'])) {
  706. return error(-1, '没有要查询的时间段');
  707. }
  708. $starttmp = date('Y-m-d', $params['starttime']);
  709. $endtmp = date('Y-m-d', $params['endtime']);
  710. if($starttmp != $endtmp) {
  711. return error(-1, '时间范围有误,微信公众平台不支持跨日查询');
  712. }
  713. if(empty($params['openid'])) {
  714. return error(-1, '没有要查询的openid');
  715. }
  716. if(empty($params['pagesize'])) {
  717. $params['pagesize'] = 50;
  718. }
  719. if(empty($params['pageindex'])) {
  720. $params['pageindex'] = 1;
  721. }
  722. $token = $this->getAccessToken();
  723. if(is_error($token)){
  724. return $token;
  725. }
  726. $url = "https://api.weixin.qq.com/customservice/msgrecord/getrecord?access_token={$token}";
  727. $response = ihttp_request($url, json_encode($params));
  728. if(is_error($response)) {
  729. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  730. }
  731. $result = @json_decode($response['content'], true);
  732. if(empty($result)) {
  733. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  734. } elseif(!empty($result['errcode'])) {
  735. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  736. }
  737. return $result;
  738. }
  739. public function isTagSupported() {
  740. return (!empty($this->account['key']) &&
  741. !empty($this->account['secret']) || $this->account['type'] == ACCOUNT_OAUTH_LOGIN) &&
  742. (intval($this->account['level']) > ACCOUNT_SERVICE);
  743. }
  744. public function fansTagAdd($tagname) {
  745. if(empty($tagname)) {
  746. return error(-1, '请填写标签名称');
  747. }
  748. $token = $this->getAccessToken();
  749. if(is_error($token)){
  750. return $token;
  751. }
  752. $url = "https://api.weixin.qq.com/cgi-bin/tags/create?access_token={$token}";
  753. $data = stripslashes(ijson_encode(array('tag' => array('name' => $tagname)), JSON_UNESCAPED_UNICODE));
  754. $result = $this->requestApi($url, $data);
  755. return $result;
  756. }
  757. public function fansTagFetchAll() {
  758. $token = $this->getAccessToken();
  759. if(is_error($token)){
  760. return $token;
  761. }
  762. $url = "https://api.weixin.qq.com/cgi-bin/tags/get?access_token={$token}";
  763. $result = $this->requestApi($url);
  764. return $result;
  765. }
  766. public function fansTagEdit($tagid, $tagname) {
  767. if(empty($tagid) || empty($tagname)) {
  768. return error(-1, '标签信息错误');
  769. }
  770. if(in_array($tagid, array(1, 2))) {
  771. return error(-1, '微信平台默认标签,不能修改');
  772. }
  773. $token = $this->getAccessToken();
  774. if(is_error($token)){
  775. return $token;
  776. }
  777. $url = "https://api.weixin.qq.com/cgi-bin/tags/update?access_token={$token}";
  778. $data = stripslashes(ijson_encode(array('tag' => array('id' => $tagid, 'name' => $tagname)), JSON_UNESCAPED_UNICODE));
  779. $result = $this->requestApi($url, $data);
  780. if (is_error($result)) {
  781. return $result;
  782. }
  783. return true;
  784. }
  785. public function fansTagDelete($tagid) {
  786. $tagid = intval($tagid);
  787. if(empty($tagid)) {
  788. return error(-1, '标签id错误');
  789. }
  790. $token = $this->getAccessToken();
  791. if(is_error($token)){
  792. return $token;
  793. }
  794. $url = "https://api.weixin.qq.com/cgi-bin/tags/delete?access_token={$token}";
  795. $data = json_encode(array('tag' => array('id' => $tagid)));
  796. $result = $this->requestApi($url, $data);
  797. if (is_error($result)) {
  798. return $result;
  799. }
  800. return true;
  801. }
  802. public function fansTagGetUserlist($tagid, $next_openid = '') {
  803. $tagid = intval($tagid);
  804. $next_openid = (string) $next_openid;
  805. if(empty($tagid)) {
  806. return error(-1, '标签id错误');
  807. }
  808. $token = $this->getAccessToken();
  809. if(is_error($token)){
  810. return $token;
  811. }
  812. $url = 'https://api.weixin.qq.com/cgi-bin/tag/get?access_token=' . $token;
  813. $data = array(
  814. 'tagid' => $tagid
  815. );
  816. if( ! empty($next_openid)){
  817. $data['next_openid'] = $next_openid;
  818. }
  819. $data = json_encode($data);
  820. $result = $this->requestApi($url, $data);
  821. return $result;
  822. }
  823. public function fansTagTagging($openid, $tagids) {
  824. $openid = (string) $openid;
  825. $tagids = (array) $tagids;
  826. if(empty($openid)){
  827. return error(-1, '没有填写用户openid');
  828. }
  829. if(empty($tagids)) {
  830. return error(-1, '没有填写标签');
  831. }
  832. if(count($tagids) > 3) {
  833. return error(-1, '最多3个标签');
  834. }
  835. $token = $this->getAccessToken();
  836. if (is_error($token)) {
  837. return $token;
  838. }
  839. $fetch_result = $this->fansTagFetchOwnTags($openid);
  840. if(is_error($fetch_result)) {
  841. return $fetch_result;
  842. }
  843. foreach($fetch_result['tagid_list'] as $del_tagid) {
  844. $this->fansTagBatchUntagging($openid, $del_tagid);
  845. }
  846. $url = "https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token={$token}";
  847. foreach($tagids as $tagid) {
  848. $data = array(
  849. 'openid_list' => $openid,
  850. 'tagid' => $tagid
  851. );
  852. $data = json_encode($data);
  853. $result = $this->requestApi($url, $data);
  854. if(is_error($result)) {
  855. return $result;
  856. }
  857. }
  858. return true;
  859. }
  860. public function fansTagBatchTagging($openid_list, $tagid) {
  861. $openid_list = (array) $openid_list;
  862. $tagid = (int) $tagid;
  863. if(empty($openid_list)){
  864. return error(-1, '没有填写用户openid列表');
  865. }
  866. if(empty($tagid)) {
  867. return error(-1, '没有填写tagid');
  868. }
  869. $token = $this->getAccessToken();
  870. if(is_error($token)){
  871. return $token;
  872. }
  873. $url = "https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token={$token}";
  874. $data = array(
  875. 'openid_list' => $openid_list,
  876. 'tagid' => $tagid
  877. );
  878. $data = json_encode($data);
  879. $result = $this->requestApi($url, $data);
  880. if(is_error($result)) {
  881. return $result;
  882. }
  883. return true;
  884. }
  885. public function fansTagBatchUntagging($openid_list, $tagid) {
  886. $openid_list = (array) $openid_list;
  887. $tagid = (int) $tagid;
  888. if(empty($openid_list)){
  889. return error(-1, '没有填写用户openid列表');
  890. }
  891. if(empty($tagid)) {
  892. return error(-1, '没有填写tagid');
  893. }
  894. $token = $this->getAccessToken();
  895. if(is_error($token)){
  896. return $token;
  897. }
  898. $url = "https://api.weixin.qq.com/cgi-bin/tags/members/batchuntagging?access_token={$token}";
  899. $data = array(
  900. 'openid_list' => $openid_list,
  901. 'tagid' => $tagid
  902. );
  903. $data = json_encode($data);
  904. $result = $this->requestApi($url, $data);
  905. if(is_error($result)) {
  906. return $result;
  907. }
  908. return true;
  909. }
  910. public function fansTagFetchOwnTags($openid) {
  911. $openid = (string) $openid;
  912. if(empty($openid)){
  913. return error(-1, '没有填写用户openid');
  914. }
  915. $token = $this->getAccessToken();
  916. if(is_error($token)){
  917. return $token;
  918. }
  919. $url = "https://api.weixin.qq.com/cgi-bin/tags/getidlist?access_token={$token}";
  920. $data = json_encode(array('openid' => $openid));
  921. $result = $this->requestApi($url, $data);
  922. return $result;
  923. }
  924. public function fansSendAll($group, $msgtype, $media_id) {
  925. $types = array('text' => 'text', 'image' => 'image', 'news' => 'mpnews', 'voice' => 'voice', 'video' => 'mpvideo', 'wxcard' => 'wxcard');
  926. if(empty($types[$msgtype])) {
  927. return error(-1, '消息类型不合法');
  928. }
  929. $is_to_all = false;
  930. if($group == - 1) {
  931. $is_to_all = true;
  932. }
  933. $send_conent = ($msgtype == 'text') ? array('content' => $media_id) : array('media_id' => $media_id);
  934. $data = array(
  935. 'filter' => array(
  936. 'is_to_all' => $is_to_all,
  937. 'group_id' => $group
  938. ),
  939. 'msgtype' => $types[$msgtype],
  940. $types[$msgtype] => $send_conent
  941. );
  942. if($msgtype == 'wxcard') {
  943. unset($data['wxcard']['media_id']);
  944. $data['wxcard']['card_id'] = $media_id;
  945. }
  946. $token = $this->getAccessToken();
  947. if(is_error($token)){
  948. return $token;
  949. }
  950. $url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token={$token}";
  951. $data = urldecode(json_encode($data, JSON_UNESCAPED_UNICODE));
  952. $response = ihttp_request($url, $data);
  953. if(is_error($response)) {
  954. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  955. }
  956. $result = @json_decode($response['content'], true);
  957. if(empty($result)) {
  958. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  959. } elseif(!empty($result['errcode'])) {
  960. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  961. }
  962. return $result;
  963. }
  964. public function fansSendPreview($wxname, $content, $msgtype) {
  965. $types = array('text' => 'text', 'image' => 'image', 'news' => 'mpnews', 'voice' => 'voice', 'video' => 'mpvideo', 'wxcard' => 'wxcard');
  966. if(empty($types[$msgtype])) {
  967. return error(-1, '群发类型不合法');
  968. }
  969. $msgtype = $types[$msgtype];
  970. $token = $this->getAccessToken();
  971. if(is_error($token)){
  972. return $token;
  973. }
  974. $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=' . $token;
  975. $send = array(
  976. 'towxname' => $wxname,
  977. 'msgtype' => $msgtype,
  978. );
  979. if($msgtype == 'text') {
  980. $send[$msgtype] = array(
  981. 'content' => $content
  982. );
  983. } elseif($msgtype == 'wxcard') {
  984. $send[$msgtype] = array(
  985. 'card_id' => $content
  986. );
  987. } else {
  988. $send[$msgtype] = array(
  989. 'media_id' => $content
  990. );
  991. }
  992. $response = ihttp_request($url, json_encode($send, JSON_UNESCAPED_UNICODE));
  993. if(is_error($response)) {
  994. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  995. }
  996. $result = @json_decode($response['content'], true);
  997. if(empty($result)) {
  998. } elseif(!empty($result['errcode'])) {
  999. return error(-1, "访问公众平台接口失败, 错误: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  1000. }
  1001. return $result;
  1002. }
  1003. public function sendCustomNotice($data) {
  1004. if(empty($data)) {
  1005. return error(-1, '参数错误');
  1006. }
  1007. $token = $this->getAccessToken();
  1008. if(is_error($token)){
  1009. return $token;
  1010. }
  1011. $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={$token}";
  1012. $response = ihttp_request($url, urldecode(json_encode($data)));
  1013. if(is_error($response)) {
  1014. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  1015. }
  1016. $result = @json_decode($response['content'], true);
  1017. if(empty($result)) {
  1018. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  1019. } elseif(!empty($result['errcode'])) {
  1020. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  1021. }
  1022. return true;
  1023. }
  1024. public function sendTplNotice($touser, $template_id, $postdata, $url = '', $topcolor = '#FF683F', $miniprogram = array('appid' => '', 'pagepath' => '')) {
  1025. if(empty($this->account['key']) || $this->account['level'] != ACCOUNT_SERVICE_VERIFY) {
  1026. return error(-1, '你的公众号没有发送模板消息的权限');
  1027. }
  1028. if(empty($touser)) {
  1029. return error(-1, '参数错误,粉丝openid不能为空');
  1030. }
  1031. if(empty($template_id)) {
  1032. return error(-1, '参数错误,模板标示不能为空');
  1033. }
  1034. if(empty($postdata) || !is_array($postdata)) {
  1035. return error(-1, '参数错误,请根据模板规则完善消息内容');
  1036. }
  1037. $token = $this->getAccessToken();
  1038. if (is_error($token)) {
  1039. return $token;
  1040. }
  1041. $data = array();
  1042. if (!empty($miniprogram['appid']) && !empty($miniprogram['pagepath'])) {
  1043. $data['miniprogram'] = $miniprogram;
  1044. }
  1045. $data['touser'] = $touser;
  1046. $data['template_id'] = trim($template_id);
  1047. $data['url'] = trim($url);
  1048. $data['topcolor'] = trim($topcolor);
  1049. $data['data'] = $postdata;
  1050. $data = json_encode($data);
  1051. $post_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$token}";
  1052. $response = ihttp_request($post_url, $data);
  1053. if(is_error($response)) {
  1054. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  1055. }
  1056. $result = @json_decode($response['content'], true);
  1057. if(empty($result)) {
  1058. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  1059. } elseif(!empty($result['errcode'])) {
  1060. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},信息详情:{$this->errorCode($result['errcode'])}");
  1061. }
  1062. return true;
  1063. }
  1064. public function uploadMedia($path, $type = 'image') {
  1065. if (empty($path)) {
  1066. return error(-1, '参数错误');
  1067. }
  1068. if (in_array(substr(ltrim($path, '/'), 0, 6), array('images', 'videos', 'audios', 'thumb'))) {
  1069. $path = ATTACHMENT_ROOT . ltrim($path, '/');
  1070. }
  1071. if (!file_exists($path)) {
  1072. return error(1, '文件不存在');
  1073. }
  1074. $token = $this->getAccessToken();
  1075. if (is_error($token)){
  1076. return $token;
  1077. }
  1078. $url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token={$token}&type={$type}";
  1079. $data = array(
  1080. 'media' => '@' . $path,
  1081. );
  1082. return $this->requestApi($url, $data);
  1083. }
  1084. public function uploadMediaFixed($path, $type = 'images') {
  1085. global $_W;
  1086. if (empty($path)) {
  1087. return error(-1, '参数错误');
  1088. }
  1089. if (in_array(substr(ltrim($path, '/'), 0, 6), array('images', 'videos', 'audios', 'thumb', 'voices'))) {
  1090. $path = ATTACHMENT_ROOT . ltrim($path, '/');
  1091. }
  1092. if (!file_exists($path)) {
  1093. return error(1, '文件不存在');
  1094. }
  1095. $token = $this->getAccessToken();
  1096. if (is_error($token)){
  1097. return $token;
  1098. }
  1099. $url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={$token}&type={$type}";
  1100. $data = array(
  1101. 'media' => '@' . $path
  1102. );
  1103. if ($type == 'videos') {
  1104. $video_filename = ltrim($path, ATTACHMENT_ROOT);
  1105. $material = $material = pdo_get('core_attachment', array('uniacid' => $_W['uniacid'], 'attachment' => $video_filename));
  1106. }
  1107. $filename = pathinfo($path, PATHINFO_FILENAME);
  1108. $description = array(
  1109. 'title' => $type == 'videos' ? $material['filename'] : $filename,
  1110. 'introduction' => $filename,
  1111. );
  1112. $data['description'] = urldecode(json_encode($description));
  1113. return $this->requestApi($url, $data);
  1114. }
  1115. public function editMaterialNews($data) {
  1116. $token = $this->getAccessToken();
  1117. if(is_error($token)){
  1118. return $token;
  1119. }
  1120. $url = "https://api.weixin.qq.com/cgi-bin/material/update_news?access_token={$token}";
  1121. $response = $this->requestApi($url, stripslashes(ijson_encode($data, JSON_UNESCAPED_UNICODE)));
  1122. if (is_error($response)) {
  1123. return $response;
  1124. }
  1125. return true;
  1126. }
  1127. public function uploadNewsThumb($thumb) {
  1128. $token = $this->getAccessToken();
  1129. if(is_error($token)){
  1130. return $token;
  1131. }
  1132. if (!file_exists($thumb)) {
  1133. return error(1, '文件不存在');
  1134. }
  1135. $data = array(
  1136. 'media' => '@'. $thumb,
  1137. );
  1138. $url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={$token}";
  1139. $response = $this->requestApi($url, $data);
  1140. if (is_error($response)) {
  1141. return $response;
  1142. } else {
  1143. return $response['url'];
  1144. }
  1145. }
  1146. public function uploadVideoFixed($title, $description, $path) {
  1147. if (empty($path) || empty($title) || empty($description)) {
  1148. return error(-1, '参数错误');
  1149. }
  1150. if (in_array(substr(ltrim($path, '/'), 0, 6), array('images', 'videos', 'audios'))) {
  1151. $path = ATTACHMENT_ROOT . ltrim($path, '/');
  1152. }
  1153. if (!file_exists($path)) {
  1154. return error(1, '文件不存在');
  1155. }
  1156. $token = $this->getAccessToken();
  1157. if (is_error($token)){
  1158. return $token;
  1159. }
  1160. $url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={$token}&type=videos";
  1161. $data = array(
  1162. 'media' => '@' . $path,
  1163. 'description' => stripslashes(ijson_encode(array('title' => $title, 'introduction' => $description), JSON_UNESCAPED_UNICODE)),
  1164. );
  1165. $response = $this->requestApi($url, $data);
  1166. return $response;
  1167. }
  1168. public function uploadVideo($data) {
  1169. if(empty($data)) {
  1170. return error(-1, '参数错误');
  1171. }
  1172. $token = $this->getAccessToken();
  1173. if(is_error($token)){
  1174. return $token;
  1175. }
  1176. $url = "https://file.api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token={$token}";
  1177. $response = ihttp_request($url, urldecode(json_encode($data)));
  1178. if(is_error($response)) {
  1179. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  1180. }
  1181. $result = @json_decode($response['content'], true);
  1182. if(empty($result)) {
  1183. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  1184. } elseif(!empty($result['errcode'])) {
  1185. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']}, 错误详情:{$this->errorCode($result['errcode'])}");
  1186. }
  1187. return $result;
  1188. }
  1189. public function uploadNews($data) {
  1190. if(empty($data)) {
  1191. return error(-1, '参数错误');
  1192. }
  1193. $token = $this->getAccessToken();
  1194. if(is_error($token)){
  1195. return $token;
  1196. }
  1197. $url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token={$token}";
  1198. $response = ihttp_request($url, urldecode(json_encode($data)));
  1199. if(is_error($response)) {
  1200. return error(-1, "访问公众平台接口失败, 错误: {$response['message']}");
  1201. }
  1202. $result = @json_decode($response['content'], true);
  1203. if(empty($result)) {
  1204. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  1205. } elseif(!empty($result['errcode'])) {
  1206. return error(-1, "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  1207. }
  1208. return $result;
  1209. }
  1210. public function addMatrialNews($data) {
  1211. $token = $this->getAccessToken();
  1212. if(is_error($token)){
  1213. return $token;
  1214. }
  1215. $url = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token={$token}";
  1216. $data = stripslashes(urldecode(ijson_encode($data, JSON_UNESCAPED_UNICODE)));
  1217. $response = $this->requestApi($url, $data);
  1218. if (is_error($response)) {
  1219. return $response;
  1220. }
  1221. return $response['media_id'];
  1222. }
  1223. public function batchGetMaterial($type = 'news', $offset = 0, $count = 20) {
  1224. global $_W;
  1225. $token = $this->getAccessToken();
  1226. if(is_error($token)){
  1227. return $token;
  1228. }
  1229. $url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=' . $token;
  1230. $data = array(
  1231. 'type' => $type,
  1232. 'offset' => intval($offset),
  1233. 'count' => $count,
  1234. );
  1235. $response = $this->requestApi($url, json_encode($data));
  1236. return $response;
  1237. }
  1238. public function getMaterial($media_id, $savefile = true) {
  1239. $token = $this->getAccessToken();
  1240. if(is_error($token)){
  1241. return $token;
  1242. }
  1243. $url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=' . $token;
  1244. $data = array(
  1245. 'media_id' => trim($media_id),
  1246. );
  1247. $response = ihttp_request($url, json_encode($data));
  1248. if(is_error($response)) {
  1249. return error(-1, "访问公平台接口失败, 错误: {$response['message']}");
  1250. }
  1251. $result = @json_decode($response['content'], true);
  1252. if(!empty($result['errcode'])) {
  1253. return error(-1, "访问公众平台接口失败, 错误: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  1254. }
  1255. if (empty($response['headers']['Content-disposition'])) {
  1256. $response = json_decode($response['content'], true);
  1257. if (!empty($response['down_url'])) {
  1258. if (empty($savefile)) {
  1259. return $response;
  1260. }
  1261. $response = ihttp_get($response['down_url']);
  1262. $response['headers']['Content-disposition'] = $response['headers']['Content-Disposition'];
  1263. } elseif (!empty($response['news_item'])) {
  1264. return $response;
  1265. }
  1266. }
  1267. if($savefile && !empty($response['headers']['Content-disposition']) && strexists($response['headers']['Content-disposition'], 'filename=')){
  1268. global $_W;
  1269. preg_match('/filename=\"?([^"]*)/', $response['headers']['Content-disposition'], $match);
  1270. $pathinfo = pathinfo($match[1]);
  1271. $filename = $_W['uniacid'].'/'.date('Y/m/');
  1272. if (in_array(strtolower($pathinfo['extension']), array('mp4'))) {
  1273. $filename = 'videos/' . $filename;
  1274. } elseif (in_array(strtolower($pathinfo['extension']), array('amr', 'mp3', 'wma', 'wmv'))) {
  1275. $filename = 'audios/' . $filename;
  1276. } else {
  1277. $filename = 'images/' . $filename;
  1278. }
  1279. $filename .= file_random_name($filename, $pathinfo['extension']);
  1280. load()->func('file');
  1281. file_write($filename, $response['content']);
  1282. file_remote_upload($filename);
  1283. return $filename;
  1284. } else {
  1285. return $response['content'];
  1286. }
  1287. return $result;
  1288. }
  1289. public function downloadMedia($media_id, $savefile = true) {
  1290. $mediatypes = array('image', 'voice', 'thumb');
  1291. $media_id = is_array($media_id) ? $media_id['media_id'] : $media_id;
  1292. if (empty($media_id)) {
  1293. return error(-1, '微信下载媒体资源参数错误');
  1294. }
  1295. $token = $this->getAccessToken();
  1296. if(is_error($token)){
  1297. return $token;
  1298. }
  1299. $url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token={$token}&media_id={$media_id}";
  1300. $response = ihttp_get($url);
  1301. if (empty($response['headers']['Content-disposition'])) {
  1302. $response = json_decode($response['content'], true);
  1303. if (!empty($response['video_url'])) {
  1304. $response = ihttp_get($response['video_url']);
  1305. $response['headers']['Content-disposition'] = $response['headers']['Content-Disposition'];
  1306. }
  1307. }
  1308. if($savefile && !empty($response['headers']['Content-disposition']) && strexists($response['headers']['Content-disposition'], 'filename=')){
  1309. global $_W;
  1310. preg_match('/filename=\"?([^"]*)/', $response['headers']['Content-disposition'], $match);
  1311. $filename = $_W['uniacid'].'/'.date('Y/m/') . $match[1];
  1312. $pathinfo = pathinfo($filename);
  1313. if (in_array(strtolower($pathinfo['extension']), array('mp4'))) {
  1314. $filename = 'videos/' . $filename;
  1315. } elseif (in_array(strtolower($pathinfo['extension']), array('amr', 'mp3', 'wma', 'wmv'))) {
  1316. $filename = 'audios/' . $filename;
  1317. } else {
  1318. $filename = 'images/' . $filename;
  1319. }
  1320. load()->func('file');
  1321. file_write($filename, $response['content']);
  1322. file_remote_upload($filename);
  1323. return $filename;
  1324. } else {
  1325. return $response['content'];
  1326. }
  1327. }
  1328. public function getMaterialCount() {
  1329. $token = $this->getAccessToken();
  1330. if(is_error($token)){
  1331. return $token;
  1332. }
  1333. $url = 'https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=' . $token;
  1334. $response = $this->requestApi($url);
  1335. return $response;
  1336. }
  1337. public function delMaterial($media_id) {
  1338. $media_id = trim($media_id);
  1339. if(empty($media_id)) {
  1340. return error(-1, '素材media_id错误');
  1341. }
  1342. $token = $this->getAccessToken();
  1343. if(is_error($token)){
  1344. return $token;
  1345. }
  1346. $url = 'https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=' . $token;
  1347. $data = array(
  1348. 'media_id' => trim($media_id),
  1349. );
  1350. $response = $this->requestApi($url, json_encode($data));
  1351. if (is_error($response)) {
  1352. return $response;
  1353. }
  1354. return true;
  1355. }
  1356. public function changeOrderStatus($send) {
  1357. if (empty($send)) {
  1358. return error(-1, '参数错误');
  1359. }
  1360. $token = $this->getAccessToken();
  1361. if(is_error($token)){
  1362. return $token;
  1363. }
  1364. $sendapi = 'https://api.weixin.qq.com/pay/delivernotify?access_token=' . $token;
  1365. $response = ihttp_request($sendapi, json_encode($send));
  1366. $response = json_decode($response['content'], true);
  1367. if (empty($response)) {
  1368. return error(-1, '发货失败,请检查您的公众号权限或是公众号AppId和公众号AppSecret!');
  1369. }
  1370. if (!empty($response['errcode'])) {
  1371. return error(-1, $response['errmsg']);
  1372. }
  1373. return $response;
  1374. }
  1375. public function getOauthUserInfo($accesstoken, $openid) {
  1376. $apiurl = "https://api.weixin.qq.com/sns/userinfo?access_token={$accesstoken}&openid={$openid}&lang=zh_CN";
  1377. $response = $this->requestApi($apiurl);
  1378. unset($response['remark'], $response['subscribe_scene'], $response['qr_scene'], $response['qr_scene_str']);
  1379. return $response;
  1380. }
  1381. public function getOauthInfo($code = '') {
  1382. global $_W, $_GPC;
  1383. if (!empty($_GPC['code'])) {
  1384. $code = $_GPC['code'];
  1385. }
  1386. if (empty($code)) {
  1387. $oauth_url = uni_account_oauth_host();
  1388. $url = $oauth_url . "app/index.php?{$_SERVER['QUERY_STRING']}";
  1389. $forward = $this->getOauthCodeUrl(urlencode($url));
  1390. header('Location: ' . $forward);
  1391. exit;
  1392. }
  1393. $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->account['key']}&secret={$this->account['secret']}&code={$code}&grant_type=authorization_code";
  1394. $response = $this->requestApi($url);
  1395. return $response;
  1396. }
  1397. public function getOauthAccessToken() {
  1398. $cachekey = cache_system_key('oauthaccesstoken', array('acid' => $this->account['acid']));
  1399. $cache = cache_load($cachekey);
  1400. if (!empty($cache) && !empty($cache['token']) && $cache['expire'] > TIMESTAMP) {
  1401. return $cache['token'];
  1402. }
  1403. $token = $this->getOauthInfo();
  1404. if (is_error($token)) {
  1405. return error(1);
  1406. }
  1407. $record = array();
  1408. $record['token'] = $token['access_token'];
  1409. $record['expire'] = TIMESTAMP + $token['expires_in'] - 200;
  1410. cache_write($cachekey, $record);
  1411. return $token['access_token'];
  1412. }
  1413. public function getShareAddressConfig() {
  1414. global $_W;
  1415. static $current_url;
  1416. if (empty($current_url)) {
  1417. $current_url = $_W['siteurl'];
  1418. }
  1419. $token = $this->getOauthAccessToken();
  1420. if (is_error($token)) {
  1421. return false;
  1422. }
  1423. $package = array(
  1424. 'appid' => $this->account['key'],
  1425. 'url' => $current_url,
  1426. 'timestamp' => strval(TIMESTAMP),
  1427. 'noncestr' => strval(random(8, true)),
  1428. 'accesstoken' => $token
  1429. );
  1430. ksort($package, SORT_STRING);
  1431. $signstring = array();
  1432. foreach ($package as $k => $v) {
  1433. $signstring[] = "{$k}={$v}";
  1434. }
  1435. $signstring = strtolower(sha1(trim(implode('&', $signstring))));
  1436. $shareaddress_config = array(
  1437. 'appId' => $this->account['key'],
  1438. 'scope' => 'jsapi_address',
  1439. 'signType' => 'sha1',
  1440. 'addrSign' => $signstring,
  1441. 'timeStamp' => $package['timestamp'],
  1442. 'nonceStr' => $package['noncestr']
  1443. );
  1444. return $shareaddress_config;
  1445. }
  1446. public function getOauthCodeUrl($callback, $state = '') {
  1447. return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->account['key']}&redirect_uri={$callback}&response_type=code&scope=snsapi_base&state={$state}#wechat_redirect";
  1448. }
  1449. public function getOauthUserInfoUrl($callback, $state = '') {
  1450. return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->account['key']}&redirect_uri={$callback}&response_type=code&scope=snsapi_userinfo&state={$state}#wechat_redirect";
  1451. }
  1452. public function getFansStat() {
  1453. global $_W;
  1454. $token = $this->getAccessToken();
  1455. if (is_error($token)) {
  1456. return $token;
  1457. }
  1458. $url = "https://api.weixin.qq.com/datacube/getusersummary?access_token={$token}";
  1459. $data = array(
  1460. 'begin_date' => date('Y-m-d', strtotime('-7 days')),
  1461. 'end_date' => date('Y-m-d', strtotime('-1 days'))
  1462. );
  1463. $summary_response = $this->requestApi($url, json_encode($data));
  1464. if (is_error($summary_response)) {
  1465. return $summary_response;
  1466. }
  1467. $url = "https://api.weixin.qq.com/datacube/getusercumulate?access_token={$token}";
  1468. $cumulate_response = $this->requestApi($url, json_encode($data));
  1469. if(is_error($cumulate_response)) {
  1470. return $cumulate_response;
  1471. }
  1472. $result = array();
  1473. if (!empty($summary_response['list'])) {
  1474. foreach ($summary_response['list'] as $row) {
  1475. $key = str_replace('-', '', $row['ref_date']);
  1476. $result[$key]['new'] = intval($result[$key]['new']) + $row['new_user'];
  1477. $result[$key]['cancel'] = intval($result[$key]['cancel']) + $row['cancel_user'];
  1478. }
  1479. }
  1480. if (!empty($cumulate_response['list'])) {
  1481. foreach ($cumulate_response['list'] as $row) {
  1482. $key = str_replace('-', '', $row['ref_date']);
  1483. $result[$key]['cumulate'] = $row['cumulate_user'];
  1484. }
  1485. }
  1486. return $result;
  1487. }
  1488. public function getComment($msg_data_id, $index, $type = 0, $begin = 0, $count = 50) {
  1489. $token = $this->getAccessToken();
  1490. $url = "https://api.weixin.qq.com/cgi-bin/comment/list?access_token={$token}";
  1491. $data = array(
  1492. 'msg_data_id' => $msg_data_id,
  1493. 'index' => $index,
  1494. 'begin' => $begin,
  1495. 'count' => $count,
  1496. 'type' => $type,
  1497. );
  1498. $response = $this->requestApi($url, json_encode($data));
  1499. return $response;
  1500. }
  1501. public function commentReply($msg_data_id, $user_comment_id, $content, $index = 0) {
  1502. $token = $this->getAccessToken();
  1503. $url = "https://api.weixin.qq.com/cgi-bin/comment/reply/add?access_token={$token}";
  1504. $data = array(
  1505. 'msg_data_id' => $msg_data_id,
  1506. 'user_comment_id' => $user_comment_id,
  1507. 'content' => $content,
  1508. 'index' => $index,
  1509. );
  1510. $response = $this->requestApi($url, stripslashes(ijson_encode($data, JSON_UNESCAPED_UNICODE)));
  1511. return $response;
  1512. }
  1513. public function commentMark($msg_data_id, $user_comment_id, $comment_type, $index = 0) {
  1514. $token = $this->getAccessToken();
  1515. if ($comment_type != 1) {
  1516. $url = "https://api.weixin.qq.com/cgi-bin/comment/markelect?access_token={$token}";
  1517. } else {
  1518. $url = "https://api.weixin.qq.com/cgi-bin/comment/unmarkelect?access_token={$token}";
  1519. }
  1520. $data = array(
  1521. 'msg_data_id' => $msg_data_id,
  1522. 'user_comment_id' => $user_comment_id,
  1523. 'index' => $index,
  1524. );
  1525. $response = $this->requestApi($url, json_encode($data));
  1526. return $response;
  1527. }
  1528. public function commentDelete($msg_data_id, $user_comment_id, $index = 0) {
  1529. $token = $this->getAccessToken();
  1530. $url = "https://api.weixin.qq.com/cgi-bin/comment/delete?access_token={$token}";
  1531. $data = array(
  1532. 'msg_data_id' => $msg_data_id,
  1533. 'user_comment_id' => $user_comment_id,
  1534. 'index' => $index,
  1535. );
  1536. $response = $this->requestApi($url, json_encode($data));
  1537. return $response;
  1538. }
  1539. public function commentReplyDelete($msg_data_id, $user_comment_id, $index = 0) {
  1540. $token = $this->getAccessToken();
  1541. $url = "https://api.weixin.qq.com/cgi-bin/comment/reply/delete?access_token={$token}";
  1542. $data = array(
  1543. 'msg_data_id' => $msg_data_id,
  1544. 'user_comment_id' => $user_comment_id,
  1545. 'index' => $index,
  1546. );
  1547. $response = $this->requestApi($url, json_encode($data));
  1548. return $response;
  1549. }
  1550. public function commentSwitch($msg_data_id, $need_open_comment, $index = 0) {
  1551. $token = $this->getAccessToken();
  1552. if ($need_open_comment == 1) {
  1553. $url = "https://api.weixin.qq.com/cgi-bin/comment/close?access_token={$token}";
  1554. } else {
  1555. $url = "https://api.weixin.qq.com/cgi-bin/comment/open?access_token={$token}";
  1556. }
  1557. $data = array(
  1558. 'msg_data_id' => $msg_data_id,
  1559. 'index' => $index,
  1560. );
  1561. $response = $this->requestApi($url, json_encode($data));
  1562. return $response;
  1563. }
  1564. protected function requestApi($url, $post = '') {
  1565. $response = ihttp_request($url, $post);
  1566. $result = @json_decode($response['content'], true);
  1567. if(is_error($response)) {
  1568. return error($result['errcode'], "访问公众平台接口失败, 错误详情: {$this->errorCode($result['errcode'])}");
  1569. }
  1570. if(empty($result)) {
  1571. return error(-1, "接口调用失败, 元数据: {$response['meta']}");
  1572. } elseif(!empty($result['errcode'])) {
  1573. return error($result['errcode'], "访问公众平台接口失败, 错误: {$result['errmsg']},错误详情:{$this->errorCode($result['errcode'])}");
  1574. }
  1575. return $result;
  1576. }
  1577. public function getMaterialSupport() {
  1578. return array(
  1579. 'mass' => array('basic' => false, 'news'=> false, 'image'=> false,'voice'=> false,'video'=> false),
  1580. 'chats' => array('basic'=> false,'news'=> false,'image'=> false,'music'=> false,'voice'=> false,'video'=> false)
  1581. );
  1582. }
  1583. }