人人商城

weixin.account.class.php 58KB

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