MiniProgramService.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace crmeb\services;
  12. use crmeb\exceptions\WechatException;
  13. use crmeb\services\easywechat\broadcast\Client;
  14. use crmeb\services\easywechat\broadcast\ServiceProvider;
  15. use crmeb\services\easywechat\orderShipping\OrderClient;
  16. use crmeb\services\easywechat\subscribe\ProgramProvider;
  17. use EasyWeChat\Core\Exceptions\HttpException;
  18. use EasyWeChat\Foundation\Application;
  19. use EasyWeChat\Material\Temporary;
  20. use EasyWeChat\MiniProgram\MiniProgram;
  21. use EasyWeChat\Payment\Order;
  22. use EasyWeChat\Payment\Payment;
  23. use EasyWeChat\Support\Collection;
  24. use Psr\Http\Message\ResponseInterface;
  25. use think\exception\ValidateException;
  26. use think\facade\Log;
  27. use think\facade\Route;
  28. /**
  29. * Class MiniProgramService
  30. * @package crmeb\services
  31. * @author xaboy
  32. * @day 2020-05-11
  33. */
  34. class MiniProgramService
  35. {
  36. /**
  37. * @var MiniProgram
  38. */
  39. protected $service;
  40. protected $config;
  41. /**
  42. * MiniProgramService constructor.
  43. * @param array $config
  44. */
  45. public function __construct(array $config)
  46. {
  47. $this->config = $config;
  48. $this->service = new Application($config);
  49. $this->service->register(new ServiceProvider());
  50. $this->service->register(new ProgramProvider());
  51. $this->service->register(new \crmeb\services\easywechat\certficates\ServiceProvider);
  52. $this->service->register(new \crmeb\services\easywechat\combinePay\ServiceProvider);
  53. $this->service->register(new \crmeb\services\easywechat\msgseccheck\ServiceProvider);
  54. $this->service->register(new \crmeb\services\easywechat\pay\ServiceProvider);
  55. $this->service->register(new \crmeb\services\easywechat\miniPayment\ServiceProvider);
  56. $this->service->register(new \crmeb\services\easywechat\batches\ServiceProvider);
  57. $this->service->register(new \crmeb\services\easywechat\orderShipping\ServiceProvider);
  58. }
  59. /**
  60. * @return Client
  61. * @author xaboy
  62. * @day 2020/7/29
  63. */
  64. public function miniBroadcast()
  65. {
  66. return $this->service->miniBroadcast;
  67. }
  68. /**
  69. * @return array[]
  70. * @author xaboy
  71. * @day 2020/6/18
  72. */
  73. public static function getConfig()
  74. {
  75. $wechat = systemConfig(['site_url', 'routine_appId', 'routine_appsecret']);
  76. $payment = systemConfig(['pay_routine_mchid', 'pay_routine_key', 'pay_routine_v3_key', 'pay_routine_serial_no_v3', 'pay_routine_client_cert', 'pay_routine_client_key', 'pay_weixin_open', 'wechat_service_merid', 'wechat_service_key', 'wechat_service_v3key', 'wechat_service_client_cert', 'wechat_service_client_key', 'wechat_service_serial_no', 'pay_routine_new_mchid','pay_routine_type','pay_routine_public_key','pay_routine_public_id']);
  77. $config = [
  78. 'app_id' => $wechat['routine_appId'],
  79. 'secret' => $wechat['routine_appsecret'],
  80. 'mini_program' => [
  81. 'app_id' => $wechat['routine_appId'],
  82. 'secret' => $wechat['routine_appsecret'],
  83. 'token' => '',
  84. 'aes_key' => '',
  85. ],
  86. 'payment' => [
  87. 'app_id' => $wechat['routine_appId'],
  88. 'merchant_id' => trim($payment['pay_routine_mchid']),
  89. 'key' => trim($payment['pay_routine_key']),
  90. 'apiv3_key' => trim($payment['pay_routine_v3_key']),
  91. 'serial_no' => trim($payment['pay_routine_serial_no_v3']),
  92. 'cert_path' => (app()->getRootPath() . 'public' . $payment['pay_routine_client_cert']),
  93. 'key_path' => (app()->getRootPath() . 'public' . $payment['pay_routine_client_key']),
  94. 'notify_url' => $wechat['site_url'] . Route::buildUrl('routineNotify')->build(),
  95. 'pay_routine_client_key' => $payment['pay_routine_client_key'],
  96. 'pay_routine_client_cert' => $payment['pay_routine_client_cert'],
  97. 'pay_routine_public_key' => $payment['pay_routine_public_key'],
  98. 'pay_routine_public_id' => $payment['pay_routine_public_id'],
  99. ],
  100. 'service_payment' => [
  101. 'merchant_id' => trim($payment['wechat_service_merid']),
  102. 'key' => trim($payment['wechat_service_key']),
  103. 'type' => 'routine',
  104. 'cert_path' => (app()->getRootPath() . 'public' . $payment['wechat_service_client_cert']),
  105. 'key_path' => (app()->getRootPath() . 'public' . $payment['wechat_service_client_key']),
  106. 'pay_weixin_client_cert' => $payment['wechat_service_client_cert'],
  107. 'pay_weixin_client_key' => $payment['wechat_service_client_key'],
  108. 'serial_no' => trim($payment['wechat_service_serial_no']),
  109. 'apiv3_key' => trim($payment['wechat_service_v3key']),
  110. 'pay_routine_public_key' => trim($payment['pay_routine_public_key']),
  111. 'pay_routine_public_id' => trim($payment['pay_routine_public_id']),
  112. ],
  113. 'pay_routine_new_mchid' => $payment['pay_routine_new_mchid'],
  114. ];
  115. $config['is_v3'] = $payment['pay_routine_type'] ? true : false;
  116. return $config;
  117. }
  118. public function isV3()
  119. {
  120. return $this->config['is_v3'];
  121. }
  122. public function v3Pay()
  123. {
  124. return $this->service->v3Pay;
  125. }
  126. /**
  127. * @return MiniProgramService
  128. * @author xaboy
  129. * @day 2020/6/2
  130. */
  131. public static function create()
  132. {
  133. return new self(self::getConfig());
  134. }
  135. /**
  136. * 支付
  137. * @return Payment
  138. */
  139. public function paymentService()
  140. {
  141. return $this->service->payment;
  142. }
  143. /**
  144. * 小程序接口
  145. * @return MiniProgram
  146. */
  147. public function miniProgram()
  148. {
  149. return $this->service->mini_program;
  150. }
  151. /**
  152. * @return \EasyWeChat\Material\Material|mixed
  153. * @author xaboy
  154. * @day 2020/7/29
  155. */
  156. public function material()
  157. {
  158. return $this->service->mini_program->material_temporary;
  159. }
  160. /**
  161. * @param $sessionKey
  162. * @param $iv
  163. * @param $encryptData
  164. * @return mixed
  165. * @author xaboy
  166. * @day 2020/6/18
  167. */
  168. public function encryptor($sessionKey, $iv, $encryptData)
  169. {
  170. return $this->miniProgram()->encryptor->decryptData($sessionKey, $iv, $encryptData);
  171. }
  172. /**
  173. * 上传临时素材接口
  174. * @return Temporary
  175. */
  176. public function materialTemporaryService()
  177. {
  178. return $this->miniProgram()->material_temporary;
  179. }
  180. /**
  181. * 客服消息接口
  182. */
  183. public function staffService()
  184. {
  185. return $this->miniProgram()->staff;
  186. }
  187. /**
  188. * @param $code
  189. * @return mixed
  190. * @author xaboy
  191. * @day 2020/6/18
  192. */
  193. public function getUserInfo($code)
  194. {
  195. $userInfo = $this->miniProgram()->sns->getSessionKey($code);
  196. return $userInfo;
  197. }
  198. /**
  199. * @return \EasyWeChat\MiniProgram\QRCode\QRCode
  200. * @author xaboy
  201. * @day 2020/6/18
  202. */
  203. public function qrcodeService()
  204. {
  205. return $this->miniProgram()->qrcode;
  206. }
  207. /**
  208. * @return OrderClient
  209. *
  210. * @date 2023/10/18
  211. * @author yyw
  212. */
  213. public function order()
  214. {
  215. return $this->service->order_ship;
  216. }
  217. /**
  218. * 生成支付订单对象
  219. * @param $openid
  220. * @param $out_trade_no
  221. * @param $total_fee
  222. * @param $attach
  223. * @param $body
  224. * @param string $detail
  225. * @param string $trade_type
  226. * @param array $options
  227. * @return Order
  228. */
  229. protected function paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = [])
  230. {
  231. $total_fee = bcmul($total_fee, 100, 0);
  232. $order = array_merge(compact('openid', 'out_trade_no', 'total_fee', 'attach', 'body', 'detail', 'trade_type'), $options);
  233. if ($order['detail'] == '') unset($order['detail']);
  234. return new Order($order);
  235. }
  236. /**
  237. * 获得下单ID
  238. * @param $openid
  239. * @param $out_trade_no
  240. * @param $total_fee
  241. * @param $attach
  242. * @param $body
  243. * @param string $detail
  244. * @param string $trade_type
  245. * @param array $options
  246. * @return mixed
  247. */
  248. public function paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = [])
  249. {
  250. $order = $this->paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options);
  251. // 获取配置 判断是否为新支付
  252. if (isset($this->config['pay_routine_new_mchid']) && $this->config['pay_routine_new_mchid']) {
  253. $result = $this->service->minipay->createorder($order);
  254. if ($result->errcode === 0) {
  255. return $result->payment_params;
  256. } else {
  257. throw new ValidateException('微信支付错误返回:' . $result->return_msg);
  258. }
  259. } else {
  260. if ($this->isV3()) {
  261. if ($trade_type == 'MWEB') $trade_type = 'H5';
  262. $payFunction = 'pay' . ucfirst($trade_type);
  263. return $this->service->v3Pay->{$payFunction}($order);
  264. } else {
  265. $result = $this->paymentService()->prepare($order);
  266. if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') {
  267. return $result->prepay_id;
  268. } else {
  269. if ($result->return_code == 'FAIL') {
  270. throw new ValidateException('微信支付错误返回:' . $result->return_msg);
  271. } else if (isset($result->err_code)) {
  272. throw new ValidateException('微信支付错误返回:' . $result->err_code_des);
  273. } else {
  274. throw new ValidateException('没有获取微信支付的预支付ID,请重新发起支付!');
  275. }
  276. }
  277. }
  278. }
  279. }
  280. /**
  281. * 获得jsSdk支付参数
  282. * @param $openid
  283. * @param $out_trade_no
  284. * @param $total_fee
  285. * @param $attach
  286. * @param $body
  287. * @param string $detail
  288. * @param string $trade_type
  289. * @param array $options
  290. * @return array|string
  291. */
  292. public function jsPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = [])
  293. {
  294. $paymentPrepare = $this->paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options);
  295. if ($this->isV3()) {
  296. return $paymentPrepare;
  297. }
  298. return $this->paymentService()->configForJSSDKPayment($paymentPrepare);
  299. }
  300. /**
  301. * 使用商户订单号退款
  302. * @param $orderNo
  303. * @param $refundNo
  304. * @param $totalFee
  305. * @param null $refundFee
  306. * @param null $opUserId
  307. * @param string $refundReason
  308. * @param string $type
  309. * @param string $refundAccount
  310. * @return Collection|ResponseInterface
  311. */
  312. public function refund($orderNo, $refundNo, $totalFee, $refundFee = null, $opUserId = null, $refundReason = '', $type = 'out_trade_no', $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS', $openId = null, $transactionId = null)
  313. {
  314. if (empty($this->config['payment']['pay_routine_client_key']) || empty($this->config['payment']['pay_routine_client_cert'])) {
  315. throw new \Exception('请配置微信支付证书');
  316. }
  317. $totalFee = floatval($totalFee);
  318. $refundFee = floatval($refundFee);
  319. if ($this->config['pay_routine_new_mchid'] ?? false) {
  320. return $this->service->minipay->refund($orderNo, $refundNo, $totalFee, $refundFee, $openId, $transactionId);
  321. } else {
  322. if ($this->isV3()) {
  323. return $this->service->v3Pay->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $type, $refundAccount, $refundReason);
  324. } else {
  325. return $this->paymentService()->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $type, $refundAccount, $refundReason);
  326. }
  327. }
  328. }
  329. /**
  330. * 发送订阅消息
  331. * @param string $touser 接收者(用户)的 openid
  332. * @param string $templateId 所需下发的订阅模板id
  333. * @param array $data 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }
  334. * @param string $link 击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
  335. * @return \EasyWeChat\Support\Collection|null
  336. * @throws \EasyWeChat\Core\Exceptions\HttpException
  337. * @throws \EasyWeChat\Core\Exceptions\InvalidArgumentException
  338. */
  339. public function sendSubscribeTemlate(string $touser, string $templateId, array $data, string $link = '')
  340. {
  341. return $this->miniprogram()->now_notice->to($touser)->template($templateId)->andData($data)->withUrl($link)->send();
  342. }
  343. /**
  344. * @param $orderNo
  345. * @param array $opt
  346. * @return bool
  347. * @author xaboy
  348. * @day 2020/6/18
  349. */
  350. public function payOrderRefund($orderNo, array $opt)
  351. {
  352. if (!isset($opt['pay_price'])) throw new ValidateException('缺少pay_price');
  353. $totalFee = floatval(bcmul($opt['pay_price'], 100, 0));
  354. $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null;
  355. $refundReason = isset($opt['refund_message']) ? $opt['refund_message'] : '无';
  356. $refundNo = isset($opt['refund_id']) ? $opt['refund_id'] : $orderNo;
  357. $opUserId = isset($opt['op_user_id']) ? $opt['op_user_id'] : null;
  358. $type = isset($opt['type']) ? $opt['type'] : 'out_trade_no';
  359. $refundAccount = isset($opt['refund_account']) ? $opt['refund_account'] : 'REFUND_SOURCE_UNSETTLED_FUNDS';
  360. $openId = $opt['open_id'] ?? null;
  361. $transactionId = $opt['transaction_id'] ?? null;
  362. try {
  363. $res = ($this->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundReason, $type, $refundAccount, $openId, $transactionId));
  364. if (isset($res->return_code) && $res->return_code == 'FAIL')
  365. throw new ValidateException('退款失败:' . $res->return_msg);
  366. if (isset($res->err_code))
  367. throw new ValidateException('退款失败:' . $res->err_code_des);
  368. } catch (\Exception $e) {
  369. throw new ValidateException($e->getMessage());
  370. }
  371. return true;
  372. }
  373. /**
  374. * @return \Symfony\Component\HttpFoundation\Response
  375. * @throws \EasyWeChat\Core\Exceptions\FaultException
  376. * @author xaboy
  377. * @day 2020/6/18
  378. */
  379. public function handleNotify()
  380. {
  381. $this->service->payment = new PaymentService($this->service->merchant);
  382. return $this->service->payment->handleNotify(function ($notify, $successful) {
  383. Log::info('小程序支付回调' . var_export($notify, 1));
  384. if (!$successful) return;
  385. try {
  386. event('pay_success_' . $notify['attach'], ['order_sn' => $notify['out_trade_no'], 'data' => $notify]);
  387. } catch (\Exception $e) {
  388. Log::info('小程序支付回调失败:' . $e->getMessage() . $e->getFile() . $e->getLine());
  389. return false;
  390. }
  391. return true;
  392. });
  393. }
  394. public function handleNotifyV3()
  395. {
  396. return $this->service->v3Pay->handleNotify(function ($notify, $successful) {
  397. Log::info('小程序支付回调v3' . var_export([$notify, $successful], 1));
  398. if (!$successful) return;
  399. try {
  400. event('pay_success_' . $notify['attach'], ['order_sn' => $notify['out_trade_no'], 'data' => $notify]);
  401. } catch (\Exception $e) {
  402. Log::info('小程序支付回调失败v3:' . $e->getMessage());
  403. return false;
  404. }
  405. return true;
  406. });
  407. }
  408. /**
  409. * @return easywechat\combinePay\Client
  410. */
  411. public function combinePay()
  412. {
  413. return $this->service->combinePay;
  414. }
  415. public function handleCombinePayNotify($type)
  416. {
  417. return $this->service->combinePay->handleNotify(function ($notify, $successful) use ($type) {
  418. Log::info('微信支付成功回调' . var_export($notify, 1));
  419. if (!$successful) return false;
  420. try {
  421. event('pay_success_' . $type, ['order_sn' => $notify['combine_out_trade_no'], 'data' => $notify, 'is_combine' => 1]);
  422. } catch (\Exception $e) {
  423. Log::info('微信支付回调失败:' . $e->getMessage());
  424. return false;
  425. }
  426. return true;
  427. });
  428. }
  429. /**
  430. * 获取模版标题的关键词列表
  431. * @param string $tid
  432. * @return mixed
  433. */
  434. public function getSubscribeTemplateKeyWords(string $tid)
  435. {
  436. // try {
  437. $res = $this->miniprogram()->now_notice->getPublicTemplateKeywords($tid);
  438. if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['data'])) {
  439. return $res['data'];
  440. } else {
  441. throw new ValidateException($res['errmsg']);
  442. }
  443. // } catch (\Throwable $e) {
  444. // throw new ValidateException($e);
  445. // }
  446. }
  447. /**
  448. * 添加订阅消息模版
  449. * @param string $tid
  450. * @param array $kidList
  451. * @param string $sceneDesc
  452. * @return mixed
  453. */
  454. public function addSubscribeTemplate(string $tid, array $kidList, string $sceneDesc = '')
  455. {
  456. try {
  457. $res = $this->miniprogram()->now_notice->addTemplate($tid, $kidList, $sceneDesc);
  458. if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['priTmplId'])) {
  459. return $res['priTmplId'];
  460. } else {
  461. throw new ValidateException($res['errmsg']);
  462. }
  463. } catch (\Throwable $e) {
  464. throw new ValidateException($e);
  465. }
  466. }
  467. public function getPrivateTemplates()
  468. {
  469. try {
  470. $res = $this->miniprogram()->now_notice->getPrivateTemplates();
  471. if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['priTmplId'])) {
  472. return $res['priTmplId'];
  473. } else {
  474. throw new ValidateException($res['errmsg']);
  475. }
  476. } catch (\Throwable $e) {
  477. throw new ValidateException($e);
  478. }
  479. }
  480. /**
  481. * 小程序 敏感词过滤
  482. * @param $userInfo
  483. * @param $content
  484. * @param $scene
  485. * @param $type
  486. * @return void
  487. * @author Qinii
  488. */
  489. public function msgSecCheck($userInfo, $content, $scene, $media_type = 0)
  490. {
  491. //$media_type 1:音频;2:图片
  492. //scene 场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)
  493. if (!in_array($scene, [1, 2, 3, 4])) {
  494. throw new ValidateException('使用场景类型错误');
  495. }
  496. if (!isset($userInfo->wechat->routine_openid)) return;
  497. $openid = $userInfo->wechat->routine_openid;
  498. if ($media_type) {
  499. return $this->service->msgSec->mediaSecCheck($content, $scene, $openid, $media_type);
  500. } else {
  501. return $this->service->msgSec->msgSecCheck($content, $scene, $openid);
  502. }
  503. }
  504. /**
  505. * 商家到零钱回调
  506. *
  507. * @param string $type
  508. * @return void
  509. */
  510. public function handleCompanyPayNotify(string $type)
  511. {
  512. return $this->service->batches->handleNotify(function ($notify) use ($type) {
  513. Log::info('小程序转账回调' . var_export($notify, 1));
  514. try {
  515. event('company_extract_status', ['type' => $type, 'data' => $notify]);
  516. } catch (\Exception $e) {
  517. Log::info('小程序转账回调失败 handle :' . $e->getMessage());
  518. return false;
  519. }
  520. return true;
  521. });
  522. }
  523. /**
  524. * V3的商家到零钱
  525. * @author Qinii
  526. * @day 2023/3/13
  527. */
  528. public function companyPay($data, $user = null)
  529. {
  530. $outBatchNo = $data['sn'];
  531. $amount = $data['price'];
  532. $openid = $data['openid'];
  533. $userName = $data['realName'] ?? '';
  534. $remark = $data['mark'] ?? '';
  535. $transferSceneId = systemConfig('transfer_scene_id');
  536. $type = 'minProgram';
  537. $transferDetailList = [
  538. [
  539. 'info_type' => '活动名称',
  540. 'info_content' => '奖金转入余额'
  541. ],
  542. [
  543. 'info_type' => '奖励说明',
  544. 'info_content' => '奖金转入余额'
  545. ]
  546. ];
  547. $result = $this->service->batches->transferBills(
  548. $outBatchNo,
  549. $amount,
  550. $openid,
  551. $userName,
  552. $remark,
  553. $transferDetailList,
  554. $transferSceneId,
  555. $type
  556. );
  557. Log::info('发起转账返回:' . json_encode($result));
  558. return $result;
  559. }
  560. /**
  561. * V2的企业到零钱
  562. * @param $data
  563. * @return mixed
  564. * @author Qinii
  565. * @day 2023/3/13
  566. */
  567. public function merchantPay($data, $user = null)
  568. {
  569. $ret = [
  570. 'partner_trade_no' => $data['sn'], //随机字符串作为订单号,跟红包和支付一个概念。
  571. 'openid' => $data['openid'], //收款人的openid
  572. 'check_name' => 'NO_CHECK', //文档中有三种校验实名的方法 NO_CHECK OPTION_CHECK FORCE_CHECK
  573. //'re_user_name'=>'张三', //OPTION_CHECK FORCE_CHECK 校验实名的时候必须提交
  574. 'amount' => $data['price'] * 100, //单位为分
  575. 'desc' => $data['mark'] ?? '',
  576. 'spbill_create_ip' => request()->ip(), //发起交易的IP地址
  577. ];
  578. $result = $this->service->merchant_pay->send($ret);
  579. if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') {
  580. return $result;
  581. } else {
  582. if ($result->return_code == 'FAIL') {
  583. throw new WechatException('微信支付错误返回:' . $result->return_msg);
  584. } else if (isset($result->err_code)) {
  585. throw new WechatException('微信支付错误返回:' . $result->err_code_des);
  586. } else {
  587. throw new WechatException('微信支付错误返回:' . $result->return_msg);
  588. }
  589. }
  590. }
  591. /**
  592. * 上传订单
  593. * @param array $order_key 订单号(商城订单好)
  594. * @param int $logistics_type 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
  595. * @param array $shipping_list 物流信息列表,发货物流单列表,支持统一发货(单个物流单)和分拆发货(多个物流单)两种模式,多重性: [1, 10]
  596. * @param string $payer_openid 支付者,支付者信息
  597. * @param int $delivery_mode 发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY
  598. * @param bool $is_all_delivered 分拆发货模式时必填,用于标识分拆发货模式下是否已全部发货完成,只有全部发货完成的情况下才会向用户推送发货完成通知。示例值: true/false
  599. * @return array
  600. *
  601. * @throws HttpException
  602. * @date 2023/05/09
  603. * @author yyw
  604. */
  605. public function uploadShippingInfo(array $order_key, int $logistics_type, array $shipping_list, string $payer_openid, string $path, int $delivery_mode = 1, bool $is_all_delivered = true, $type = '')
  606. {
  607. return $this->order()->uploadShippingInfo($order_key, $logistics_type, $shipping_list, $payer_openid, $path, $delivery_mode, $is_all_delivered);
  608. }
  609. }