|
|
@@ -0,0 +1,226 @@
|
|
|
+<?php
|
|
|
+namespace app\common\service\pay;
|
|
|
+use app\common\enum\PayEnum;
|
|
|
+use app\common\enum\user\UserTerminalEnum;
|
|
|
+use app\common\logic\PayNotifyLogic;
|
|
|
+use app\common\model\master_worker\MasterWorkerAuth;
|
|
|
+use app\common\model\recharge\RechargeOrder;
|
|
|
+use app\common\model\user\UserAuth;
|
|
|
+use app\common\service\wechat\WeChatConfigService;
|
|
|
+use app\common\service\wechat\WorkerWeChatConfigService;
|
|
|
+use EasyWeChat\Pay\Application;
|
|
|
+use EasyWeChat\Pay\Message;
|
|
|
+use think\facade\Log;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 微信支付
|
|
|
+ * Class WorkerWeChatPayService
|
|
|
+ * @package app\common\server
|
|
|
+ */
|
|
|
+class WorkerWeChatPayService extends BasePayService
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 授权信息
|
|
|
+ * @var UserAuth|array|\think\Model
|
|
|
+ */
|
|
|
+ protected $auth;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 微信配置
|
|
|
+ * @var
|
|
|
+ */
|
|
|
+ protected $config;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * easyWeChat实例
|
|
|
+ * @var
|
|
|
+ */
|
|
|
+ protected $app;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当前使用客户端
|
|
|
+ * @var
|
|
|
+ */
|
|
|
+ protected $terminal;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化微信支付配置
|
|
|
+ * @param $terminal //用户终端
|
|
|
+ * @param null $userId //用户id(获取授权openid)
|
|
|
+ */
|
|
|
+ public function __construct($terminal, $userId = null)
|
|
|
+ {
|
|
|
+ $this->terminal = $terminal;
|
|
|
+ $this->config = WeChatConfigService::getPayConfigByTerminal($terminal);
|
|
|
+ $this->app = new Application($this->config);
|
|
|
+ if ($userId !== null) {
|
|
|
+ $this->auth = MasterWorkerAuth::where(['worker_id' => $userId, 'terminal' => $terminal])->findOrEmpty();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @notes 发起微信支付统一下单
|
|
|
+ * @param $from
|
|
|
+ * @param $order
|
|
|
+ * @return array|false|string
|
|
|
+ * @author 段誉
|
|
|
+ * @date 2021/8/4 15:05
|
|
|
+ */
|
|
|
+ public function pay($from, $order)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ switch ($this->terminal) {
|
|
|
+ case UserTerminalEnum::WECHAT_MMP:
|
|
|
+ $config = WorkerWeChatConfigService::getMnpConfig();
|
|
|
+ $result = $this->jsapiPay($from, $order, $config['app_id']);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new \Exception('支付方式错误');
|
|
|
+ }
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'config' => $result,
|
|
|
+ 'pay_way' => PayEnum::WECHAT_PAY
|
|
|
+ ];
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $this->setError($e->getMessage());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @notes jsapiPay
|
|
|
+ * @param $from
|
|
|
+ * @param $order
|
|
|
+ * @param $appId
|
|
|
+ * @return mixed
|
|
|
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
|
|
|
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
|
|
|
+ * @author 段誉
|
|
|
+ * @date 2023/2/28 12:12
|
|
|
+ */
|
|
|
+ public function jsapiPay($from, $order, $appId)
|
|
|
+ {
|
|
|
+ $response = $this->app->getClient()->postJson("v3/pay/transactions/jsapi", [
|
|
|
+ "appid" => $appId,
|
|
|
+ "mchid" => $this->config['mch_id'],
|
|
|
+ "description" => $this->payDesc($from),
|
|
|
+ "out_trade_no" => $order['pay_sn'],
|
|
|
+ "notify_url" => $this->config['notify_url'],
|
|
|
+ "amount" => [
|
|
|
+ "total" => intval($order['order_amount'] * 100),
|
|
|
+ ],
|
|
|
+ "payer" => [
|
|
|
+ "openid" => $this->auth['openid']
|
|
|
+ ],
|
|
|
+ 'attach' => $from
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $result = $response->toArray(false);
|
|
|
+ $this->checkResultFail($result);
|
|
|
+ return $this->getPrepayConfig($result['prepay_id'], $appId);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @notes 支付描述
|
|
|
+ * @param $from
|
|
|
+ * @return string
|
|
|
+ * @author 段誉
|
|
|
+ * @date 2023/2/27 17:54
|
|
|
+ */
|
|
|
+ public function payDesc($from)
|
|
|
+ {
|
|
|
+ $desc = [
|
|
|
+ 'goods' => '商品',
|
|
|
+ 'recharge' => '充值',
|
|
|
+ ];
|
|
|
+ return $desc[$from] ?? '商品';
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @notes 捕获错误
|
|
|
+ * @param $result
|
|
|
+ * @throws \Exception
|
|
|
+ * @author 段誉
|
|
|
+ * @date 2023/2/28 12:09
|
|
|
+ */
|
|
|
+ public function checkResultFail($result)
|
|
|
+ {
|
|
|
+ if (!empty($result['code']) || !empty($result['message'])) {
|
|
|
+ throw new \Exception('微信:'. $result['code'] . '-' . $result['message']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @notes 预支付配置
|
|
|
+ * @param $prepayId
|
|
|
+ * @param $appId
|
|
|
+ * @return mixed[]
|
|
|
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
|
|
|
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
|
|
|
+ * @author 段誉
|
|
|
+ * @date 2023/2/28 17:38
|
|
|
+ */
|
|
|
+ public function getPrepayConfig($prepayId, $appId)
|
|
|
+ {
|
|
|
+ return $this->app->getUtils()->buildBridgeConfig($prepayId, $appId);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @notes 支付回调
|
|
|
+ * @return \Psr\Http\Message\ResponseInterface
|
|
|
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
|
|
|
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
|
|
|
+ * @throws \ReflectionException
|
|
|
+ * @throws \Throwable
|
|
|
+ * @author 段誉
|
|
|
+ * @date 2023/2/28 14:20
|
|
|
+ */
|
|
|
+ public function notify()
|
|
|
+ {
|
|
|
+ $server = $this->app->getServer();
|
|
|
+ // 支付通知
|
|
|
+ $server->handlePaid(function (Message $message) {
|
|
|
+ Log::write(json_encode($message, JSON_UNESCAPED_UNICODE));
|
|
|
+ if ($message['trade_state'] === 'SUCCESS') {
|
|
|
+ $extra['transaction_id'] = $message['transaction_id'];
|
|
|
+ $attach = $message['attach'];
|
|
|
+ $message['out_trade_no'] = mb_substr($message['out_trade_no'], 0, 18);
|
|
|
+ $order = RechargeOrder::where(['sn' => $message['out_trade_no']])->findOrEmpty();
|
|
|
+ if($order->isEmpty() || $order->pay_status == PayEnum::ISPAID) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ switch ($attach) {
|
|
|
+ case 'recharge':
|
|
|
+ PayNotifyLogic::handle('recharge', $message['out_trade_no'], $extra);
|
|
|
+ break;
|
|
|
+ case 'goods':
|
|
|
+ PayNotifyLogic::handle('goods', $message['out_trade_no'], $extra);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 退款通知
|
|
|
+ $server->handleRefunded(function (Message $message) {
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ return $server->serve();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|