WechatService.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. <?php
  2. namespace liuniu;
  3. use app\admin\model\Company;
  4. use app\admin\model\WechatPlanRecord;
  5. use app\common\model\LaveMonth;
  6. use app\common\model\WechatContext;
  7. use EasyWeChat\Factory;
  8. use EasyWeChat\Kernel\Messages\Article;
  9. use EasyWeChat\Kernel\Messages\Image;
  10. use EasyWeChat\Kernel\Messages\News;
  11. use EasyWeChat\Kernel\Messages\Text;
  12. use EasyWeChat\Kernel\Messages\Video;
  13. use think\Hook;
  14. use think\Request;
  15. use think\Response;
  16. class WechatService
  17. {
  18. private static $instance = null;
  19. private static $app = null;
  20. public static function options($cid)
  21. {
  22. $info = Company::where('id', $cid)->find();
  23. $config = [
  24. 'app_id' => isset($info['wechat_appid']) ? trim($info['wechat_appid']) : '',
  25. 'secret' => isset($info['wechat_appsecret']) ? trim($info['wechat_appsecret']) : '',
  26. 'token' => isset($info['wechat_token']) ? trim($info['wechat_token']) : '',
  27. 'guzzle' => [
  28. 'timeout' => 10.0, // 超时时间(秒)
  29. 'verify' => false
  30. ],
  31. ];
  32. if (isset($info['wechat_encode']) && (int)$info['wechat_encode'] > 0 && isset($info['wechat_encodingaeskey']) && !empty($info['wechat_encodingaeskey']))
  33. $config['aes_key'] = $info['wechat_encodingaeskey'];
  34. if (isset($info['pay_weixin_open']) && $info['pay_weixin_open'] == 1) {
  35. $config1 = [
  36. 'mch_id' => trim($info['pay_weixin_mchid']),
  37. 'key' => trim($info['pay_weixin_key']),
  38. 'cert_path' => realpath('.' . $info['pay_weixin_client_certfile']),
  39. 'key_path' => realpath('.' . $info['pay_weixin_client_keyfile']),
  40. 'notify_url' => Request::instance()->domain() . "/api/wechat/notify/" . $cid
  41. ];
  42. $config = array_merge($config, $config1);
  43. }
  44. return $config;
  45. }
  46. public static function application($cache = false, $cid = 0)
  47. {
  48. (self::$instance[$cid] === null || $cache === true) && (self::$instance[$cid] = Factory::officialAccount(self::options($cid)));
  49. return self::$instance[$cid];
  50. }
  51. /**
  52. * 支付接口
  53. * @param false $cache
  54. * @param int $cid
  55. * @return \EasyWeChat\Payment\Application|mixed
  56. */
  57. public static function payment($cache = false, $cid = 0)
  58. {
  59. (self::$app[$cid] === null || $cache === true) && (self::$app[$cid] = Factory::payment(self::options($cid)));
  60. return self::$app[$cid];
  61. }
  62. public static function serve($cid = 0): Response
  63. {
  64. $wechat = self::application(true, $cid);
  65. $server = $wechat->server;
  66. self::hook($server);
  67. $response = $server->serve();
  68. return Response($response->getContent());
  69. }
  70. /**
  71. * 监听行为
  72. * @param Guard $server
  73. */
  74. private static function hook($server)
  75. {
  76. $server->push(function ($message) {
  77. switch ($message['MsgType']) {
  78. case 'event':
  79. switch (strtolower($message['Event'])) {
  80. case 'subscribe':
  81. $response = WechatReply::reply('subscribe');
  82. if (isset($message->EventKey)) {
  83. if ($message->EventKey && ($qrInfo = QrcodeService::getQrcode($message->Ticket, 'ticket'))) {
  84. QrcodeService::scanQrcode($message->Ticket, 'ticket');
  85. if (strtolower($qrInfo['third_type']) == 'spread') {
  86. }
  87. }
  88. }
  89. break;
  90. case 'unsubscribe':
  91. event('WechatEventUnsubscribeBefore', [$message]);
  92. break;
  93. case 'scan':
  94. $response = WechatReply::reply('subscribe');
  95. if ($message->EventKey && ($qrInfo = QrcodeService::getQrcode($message->Ticket, 'ticket'))) {
  96. QrcodeService::scanQrcode($message->Ticket, 'ticket');
  97. if (strtolower($qrInfo['third_type']) == 'spread') {
  98. }
  99. }
  100. break;
  101. case 'location':
  102. $response = MessageRepositories::wechatEventLocation($message);
  103. break;
  104. case 'click':
  105. $response = WechatReply::reply($message->EventKey);
  106. break;
  107. case 'view':
  108. $response = MessageRepositories::wechatEventView($message);
  109. break;
  110. }
  111. break;
  112. case 'text':
  113. @file_put_contents("tt.txt", '1');
  114. $response = self::textMessage('绑定推荐人失败');
  115. @file_put_contents("tt.txt", '2', 8);
  116. @file_put_contents("tt.txt", json_encode($response), 8);
  117. break;
  118. $response = WechatReply::reply($message->Content);
  119. break;
  120. case 'image':
  121. $response = MessageRepositories::wechatMessageImage($message);
  122. break;
  123. case 'voice':
  124. $response = MessageRepositories::wechatMessageVoice($message);
  125. break;
  126. case 'video':
  127. $response = MessageRepositories::wechatMessageVideo($message);
  128. break;
  129. case 'location':
  130. $response = MessageRepositories::wechatMessageLocation($message);
  131. break;
  132. case 'link':
  133. $response = MessageRepositories::wechatMessageLink($message);
  134. break;
  135. // ... 其它消息
  136. default:
  137. $response = MessageRepositories::wechatMessageOther($message);
  138. break;
  139. }
  140. return $response ?? false;
  141. });
  142. }
  143. /**
  144. * 多客服消息转发
  145. * @param string $account
  146. * @return \EasyWeChat\Message\Transfer
  147. */
  148. public static function transfer($account = '')
  149. {
  150. $transfer = new \EasyWeChat\Message\Transfer();
  151. return empty($account) ? $transfer : $transfer->to($account);
  152. }
  153. /**
  154. * 上传永久素材接口
  155. * @return \EasyWeChat\Material\Material
  156. */
  157. public static function materialService($cid = 0)
  158. {
  159. return self::application(false, $cid)->material;
  160. }
  161. /**
  162. * 上传临时素材接口
  163. * @return \EasyWeChat\Material\Temporary
  164. */
  165. public static function materialTemporaryService($cid = 0)
  166. {
  167. return self::application(false, $cid)->media;
  168. }
  169. /**
  170. * 用户接口
  171. * @return \EasyWeChat\User\User
  172. */
  173. public static function userService($cid = 0)
  174. {
  175. return self::application(false, $cid)->user;
  176. }
  177. /**
  178. * 客服消息接口
  179. * @param null $to
  180. * @param null $message
  181. */
  182. public static function staffService($cid = 0)
  183. {
  184. return self::application(false, $cid)->staff;
  185. }
  186. /**
  187. * 微信公众号菜单接口
  188. * @return \EasyWeChat\Menu\Menu
  189. */
  190. public static function menuService($cid = 0)
  191. {
  192. return self::application(false, $cid)->menu;
  193. }
  194. /**
  195. * 微信二维码生成接口
  196. * @return \EasyWeChat\QRCode\QRCode
  197. */
  198. public static function qrcodeService($cid = 0)
  199. {
  200. return self::application(false, $cid)->qrcode;
  201. }
  202. /**
  203. * 微信永久二维码生成接口 小于10万个
  204. * @return \EasyWeChat\QRCode\QRCode
  205. */
  206. public static function qrcodeForeverService($sceneValue, $cid = 0)
  207. {
  208. return self::application(false, $cid)->qrcode->forever($sceneValue);
  209. }
  210. /**
  211. * 微信临时二维码生成接口 30天有效期
  212. * @return \EasyWeChat\QRCode\QRCode
  213. */
  214. public static function qrcodeTempService($sceneValue, $expireSeconds = 2592000, $cid = 0)
  215. {
  216. return self::application(false, $cid)->qrcode->temporary($sceneValue, $expireSeconds);
  217. }
  218. /**
  219. * 短链接生成接口
  220. * @return \EasyWeChat\Url\Url
  221. */
  222. public static function urlService($cid = 0)
  223. {
  224. return self::application(false, $cid)->url;
  225. }
  226. /**
  227. * 用户授权
  228. * @return \Overtrue\Socialite\Providers\WeChatProvider
  229. */
  230. public static function oauthService($cid = 0)
  231. {
  232. return self::application(false, $cid)->oauth;
  233. }
  234. /**
  235. * 模板消息接口
  236. * @return \EasyWeChat\Notice\Notice
  237. */
  238. public static function noticeService($cid = 0)
  239. {
  240. return self::application(false, $cid)->template_message;
  241. }
  242. public static function sendTemplate($openid, $templateId, array $data, $url = null, $cid = 0)
  243. {
  244. $notice = self::noticeService($cid);
  245. return $notice->send([
  246. 'touser' => $openid,
  247. 'template_id' => $templateId,
  248. 'url' => $url,
  249. 'data' => $data,
  250. ]);
  251. }
  252. public static function userTagService($cid = 0)
  253. {
  254. return self::application(false, $cid)->user_tag;
  255. }
  256. /**
  257. * 生成支付订单对象
  258. * @param $openid
  259. * @param $out_trade_no
  260. * @param $total_fee
  261. * @param $attach
  262. * @param $body
  263. * @param string $detail
  264. * @param string $trade_type
  265. * @param array $options
  266. * @return Order
  267. */
  268. public static function paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = [], $cid = 0)
  269. {
  270. $total_fee = bcmul($total_fee, 100, 0);
  271. $order = array_merge(compact('out_trade_no', 'total_fee', 'attach', 'body', 'detail', 'trade_type', 'openid'), $options);
  272. if ($order['detail'] == '') unset($order['detail']);
  273. @file_put_contents("quanju.txt", json_encode($order)."-微信支付传值\r\n", 8);
  274. $result = self::payment(false, $cid)->order->unify(
  275. $order
  276. );
  277. return $result;
  278. }
  279. /**
  280. * 使用商户订单号退款
  281. * @param $orderNo
  282. * @param $opt
  283. */
  284. public static function payOrderRefund($cid, $orderNo, array $opt)
  285. {
  286. if (!isset($opt['pay_price'])) exception('缺少pay_price');
  287. $totalFee = floatval(bcmul($opt['pay_price'], 100, 0));
  288. $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null;
  289. $refundReason = isset($opt['desc']) ? $opt['desc'] : '';
  290. $refundNo = isset($opt['refund_id']) ? $opt['refund_id'] : $orderNo;
  291. $opUserId = isset($opt['op_user_id']) ? $opt['op_user_id'] : null;
  292. $type = isset($opt['type']) ? $opt['type'] : 'out_trade_no';
  293. /*仅针对老资金流商户使用
  294. REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款)
  295. REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款*/
  296. $refundAccount = isset($opt['refund_account']) ? $opt['refund_account'] : 'REFUND_SOURCE_UNSETTLED_FUNDS';
  297. try {
  298. $res = self::payment('false', $cid)->byOutTradeNumber($orderNo, $refundNo, $totalFee, $refundFee, ['refund_desc' => $refundReason]);
  299. if ($res->return_code == 'FAIL') exception('退款失败:' . $res->return_msg);
  300. if (isset($res->err_code)) exception('退款失败:' . $res->err_code_des);
  301. } catch (\Exception $e) {
  302. exception($e->getMessage());
  303. }
  304. return true;
  305. }
  306. /**
  307. * 微信支付成功回调接口
  308. */
  309. public static function handleNotify($cid)
  310. {
  311. $response = self::payment(true, $cid)->handlePaidNotify(function ($notify, $successful) use ($cid) {
  312. if ($successful && isset($notify['out_trade_no'])) {
  313. if (isset($notify['attach']) && $notify['attach']) {
  314. if (($count = strpos($notify['out_trade_no'], '_')) !== false) {
  315. $notify['out_trade_no'] = substr($notify['out_trade_no'], $count + 1);
  316. }
  317. $params = [$cid, $notify['out_trade_no']];
  318. Hook::exec("\\liuniu\\repositories\\PaymentRepositories", "wechat" . ucfirst($notify['attach']), $params);
  319. }
  320. $data = ['eventkey' => 'notify', 'command' => '', 'refreshtime' => time(), 'openid' => $notify['openid'], 'message' => json_encode($notify)];
  321. $wechatContext = WechatContext::create($data, true);
  322. return true;
  323. }
  324. @file_put_contents("quanju.txt", json_encode($notify)."-签约返回内容\r\n", 8);
  325. // @file_put_contents("quanju.txt", json_encode($successful)."-这是什么\r\n", 8);
  326. if (isset($notify['plan_id'])) {
  327. if (isset($notify['change_type']) && $notify['change_type']) {
  328. @file_put_contents("quanju.txt", $notify['change_type']."-状态\r\n", 8);
  329. if ($notify['change_type']=='ADD'){
  330. $cs=WechatPlanRecord::where('contract_code',$notify['contract_code'])->Update(['contract_id' => $notify['contract_id'],'is_signing'=>0]);
  331. if (($count = strpos($notify['contract_code'], '_')) !== false) {
  332. $notify['contract_code'] = substr($notify['contract_code'], $count + 1);
  333. }
  334. $params = [$cid, $notify['contract_code']];
  335. Hook::exec("\\liuniu\\repositories\\PaymentRepositories", "wechat" . ucfirst('MonthLave'), $params);
  336. @file_put_contents("quanju.txt", json_encode($params)."-不知道行不行\r\n", 8);
  337. }elseif ($notify['change_type']=='DELETE'){
  338. @file_put_contents("quanju.txt", "-关闭签约\r\n", 8);
  339. $cs=WechatPlanRecord::where('contract_code',$notify['contract_code'])->Update(['is_signing' => 1,'deletetime'=>time()]);
  340. }
  341. @file_put_contents("quanju.txt", $cs."-修改记录\r\n", 8);
  342. }
  343. $data = ['eventkey' => 'notify', 'command' => '', 'refreshtime' => time(), 'openid' => $notify['openid'], 'message' => json_encode($notify)];
  344. $wechatContext = WechatContext::create($data, true);
  345. return true;
  346. }
  347. if (isset($notify['nonce_str'])) {
  348. $cz = LaveMonth::Where(['contract_code' => $notify['nonce_str']])->find();
  349. @file_put_contents("quanju.txt", json_encode($cz)."-随机字符搜索\r\n", 8);
  350. if (!empty($cz)){
  351. $params = [$cid, $notify['nonce_str']];
  352. Hook::exec("\\liuniu\\repositories\\PaymentRepositories", "wechat" . ucfirst('MonthLavePay'), $params);
  353. }
  354. $data = ['eventkey' => 'notify', 'command' => '', 'refreshtime' => time(), 'openid' => $notify['openid'], 'message' => json_encode($notify)];
  355. $wechatContext = WechatContext::create($data, true);
  356. return true;
  357. }
  358. });
  359. $response->send();
  360. }
  361. /**
  362. * jsSdk
  363. * @return \EasyWeChat\Js\Js
  364. */
  365. public static function jsService($cid = 0)
  366. {
  367. return self::payment(false, $cid)->jssdk;
  368. }
  369. public static function WeixinJSBridge($cid, $prepayId)
  370. {
  371. $json = self::jsService($cid)->bridgeConfig($prepayId);
  372. return $json;
  373. }
  374. public static function jspay($cid, $prepayId)
  375. {
  376. $json = self::jsService($cid)->sdkConfig($prepayId);
  377. return $json;
  378. }
  379. public static function jsSdk($url = '', $cid = 0)
  380. {
  381. $apiList = ['editAddress', 'openAddress', 'updateTimelineShareData', 'updateAppMessageShareData', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard'];
  382. $jsService = self::jsService($cid);
  383. if ($url) $jsService->setUrl($url);
  384. try {
  385. return $jsService->buildConfig($apiList, false);
  386. } catch (\Exception $e) {
  387. // var_dump($e->getMessage());
  388. return '{}';
  389. }
  390. }
  391. /**
  392. * 回复文本消息
  393. * @param string $content 文本内容
  394. * @return Text
  395. */
  396. public static function textMessage($content)
  397. {
  398. return new Text($content);
  399. }
  400. /**
  401. * 回复图片消息
  402. * @param string $media_id 媒体资源 ID
  403. * @return Image
  404. */
  405. public static function imageMessage($media_id)
  406. {
  407. return new Image('media_id');
  408. }
  409. /**
  410. * 回复视频消息
  411. * @param string $media_id 媒体资源 ID
  412. * @param string $title 标题
  413. * @param string $description 描述
  414. * @param null $thumb_media_id 封面资源 ID
  415. * @return Video
  416. */
  417. public static function videoMessage($media_id, $title = '', $description = '...', $thumb_media_id = null)
  418. {
  419. return new Video(compact('media_id', 'title', 'description', 'thumb_media_id'));
  420. }
  421. /**
  422. * 回复声音消息
  423. * @param string $media_id 媒体资源 ID
  424. * @return Voice
  425. */
  426. public static function voiceMessage($media_id)
  427. {
  428. return new Voice(compact('media_id'));
  429. }
  430. /**
  431. * 回复图文消息
  432. * @param string|array $title 标题
  433. * @param string $description 描述
  434. * @param string $url URL
  435. * @param string $image 图片链接
  436. */
  437. public static function newsMessage($title, $description = '...', $url = '', $image = '')
  438. {
  439. if (is_array($title)) {
  440. if (isset($title[0]) && is_array($title[0])) {
  441. $newsList = [];
  442. foreach ($title as $news) {
  443. $newsList[] = self::newsMessage($news);
  444. }
  445. return $newsList;
  446. } else {
  447. $data = $title;
  448. }
  449. } else {
  450. $data = compact('title', 'description', 'url', 'image');
  451. }
  452. return new News($data);
  453. }
  454. /**
  455. * 回复文章消息
  456. * @param string|array $title 标题
  457. * @param string $thumb_media_id 图文消息的封面图片素材id(必须是永久 media_ID)
  458. * @param string $source_url 图文消息的原文地址,即点击“阅读原文”后的URL
  459. * @param string $content 图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,且此处会去除JS
  460. * @param string $author 作者
  461. * @param string $digest 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空
  462. * @param int $show_cover_pic 是否显示封面,0为false,即不显示,1为true,即显示
  463. * @param int $need_open_comment 是否打开评论,0不打开,1打开
  464. * @param int $only_fans_can_comment 是否粉丝才可评论,0所有人可评论,1粉丝才可评论
  465. * @return Article
  466. */
  467. public static function articleMessage($title, $thumb_media_id, $source_url, $content = '', $author = '', $digest = '', $show_cover_pic = 0, $need_open_comment = 0, $only_fans_can_comment = 1)
  468. {
  469. $data = is_array($title) ? $title : compact('title', 'thumb_media_id', 'source_url', 'content', 'author', 'digest', 'show_cover_pic', 'need_open_comment', 'only_fans_can_comment');
  470. return new Article($data);
  471. }
  472. /**
  473. * 作为客服消息发送
  474. * @param $to
  475. * @param $message
  476. * @return bool
  477. */
  478. public static function staffTo($to, $message)
  479. {
  480. $staff = self::staffService();
  481. $staff = is_callable($message) ? $staff->message($message()) : $staff->message($message);
  482. $res = $staff->to($to)->send();
  483. return $res;
  484. }
  485. /**
  486. * 获得用户信息
  487. * @param array|string $openid
  488. * @return \EasyWeChat\Support\Collection
  489. */
  490. public static function getUserInfo($cid, $openid)
  491. {
  492. $userService = self::userService($cid);
  493. $userInfo = is_array($openid) ? $userService->select($openid) : $userService->get($openid);
  494. return $userInfo;
  495. }
  496. /**
  497. * 生成支付签约订单对象
  498. * @param $openid
  499. * @param $out_trade_no
  500. * @param $total_fee
  501. * @param $attach
  502. * @param $body
  503. * @param string $detail
  504. * @param string $trade_type
  505. * @param array $options
  506. * @return Order
  507. */
  508. public static function paysignedOrder($openid, $out_trade_no, $total_fee, $attach, $body,$contract_code, $plan_id,$spbill_create_ip,$detail = '', $trade_type = 'JSAPI', $options = [], $cid = 0,$contract_display_account='')
  509. {
  510. $total_fee = bcmul($total_fee, 100, 0);
  511. $order = array_merge(compact('out_trade_no', 'total_fee', 'attach', 'body', 'detail', 'trade_type', 'openid','contract_code','plan_id','spbill_create_ip','contract_display_account'), $options);
  512. if ($order['detail'] == '') unset($order['detail']);
  513. $order['contract_notify_url']=Request::instance()->domain() . "/api/wechat/notify/" . $cid;
  514. $result = self::payment(false, $cid)->order->unify(
  515. $order,true
  516. );
  517. // var_dump($result);die();
  518. @file_put_contents("quanju.txt", json_encode($result) . "-签约返回结果\r\n", 8);
  519. return $result;
  520. }
  521. /**
  522. * 签约申请扣款
  523. * @param $openid
  524. * @param $out_trade_no
  525. * @param $total_fee
  526. * @param $attach
  527. * @param $body
  528. * @param string $detail
  529. * @param string $trade_type
  530. * @param array $options
  531. * @return Order
  532. */
  533. public static function papPayApply($mch_id,$out_trade_no, $total_fee, $attach, $detail = '', $trade_type = 'PAP', $options = [], $cid = 0,$contract_id='',$body='月捐款',$nonce_str='')
  534. {
  535. $total_fee = bcmul($total_fee, 100, 0);
  536. $order = array_merge(compact('mch_id','out_trade_no', 'total_fee', 'attach', 'detail', 'trade_type','contract_id','body','nonce_str'), $options);
  537. if ($order['detail'] == '') unset($order['detail']);
  538. $order['notify_url']=Request::instance()->domain() . "/api/wechat/notify/" . $cid;
  539. $result = self::payment(false, $cid)->contract->apply(
  540. $order
  541. );
  542. var_dump($result);die();
  543. return $result;
  544. }
  545. /**
  546. * 解除签约
  547. */
  548. public static function deleteSign($mch_id,$contract_code,$plan_id,$version='1.0',$options=[],$cid=0)
  549. {
  550. $contract_termination_remark = '月捐款解约';
  551. $order = array_merge(compact('mch_id','contract_code','plan_id','version','contract_termination_remark'), $options);
  552. // if ($order['detail'] == '') unset($order['detail']);
  553. // $order['notify_url']=Request::instance()->domain() . "/api/wechat/notify/" . $cid;
  554. $result = self::payment(false, $cid)->contract->delete(
  555. $order
  556. );
  557. return $result;
  558. }
  559. /**
  560. * 查询签约
  561. */
  562. public static function querySign($mch_id,$contract_code,$pan_id,$version='1.0',$options=[],$cid=0)
  563. {
  564. $appid='wx5681205d1ef4d9d3';
  565. $order = array_merge(compact('appid','mch_id','contract_code','pan_id','version'), $options);
  566. // if ($order['detail'] == '') unset($order['detail']);
  567. // $order['notify_url']=Request::instance()->domain() . "/api/wechat/notify/" . $cid;
  568. $result = self::payment(false, $cid)->contract->query(
  569. $order
  570. );
  571. @file_put_contents("quanju.txt", json_encode($result) . "-查询签约状态返回结果\r\n", 8);
  572. return $result;
  573. }
  574. }