|
@@ -4,6 +4,8 @@ namespace App\Services;
|
|
|
|
|
|
|
|
use App\Constants\HttpStatus;
|
|
use App\Constants\HttpStatus;
|
|
|
use App\Models\PaymentOrder;
|
|
use App\Models\PaymentOrder;
|
|
|
|
|
+use App\Models\Agent\AgentPaymentOrder;
|
|
|
|
|
+use App\Services\Agent\AgentPaymentService;
|
|
|
use App\Models\RechargeChannel;
|
|
use App\Models\RechargeChannel;
|
|
|
use App\Models\User;
|
|
use App\Models\User;
|
|
|
use App\Models\Wallet as WalletModel;
|
|
use App\Models\Wallet as WalletModel;
|
|
@@ -223,6 +225,23 @@ class PaymentOrderService extends BaseService
|
|
|
return $result;
|
|
return $result;
|
|
|
}
|
|
}
|
|
|
$bonusSnapshot = RechargeBonusService::capture((string)$channelConfig->type, (string)$memberId);
|
|
$bonusSnapshot = RechargeBonusService::capture((string)$channelConfig->type, (string)$memberId);
|
|
|
|
|
+ $extra = $bonusSnapshot === null ? [] : ['recharge_bonus_snapshot' => $bonusSnapshot];
|
|
|
|
|
+ return self::createPayOrder(PaymentOrder::class, $memberId, $amount, $paymentType, $groupId, $channelConfig, $extra);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 按通道向三方(808/NO/JD/三斤)发起代收并保存订单。会员和代理共用:
|
|
|
|
|
+ * - $model:PaymentOrder(会员)或 AgentPaymentOrder(代理);
|
|
|
|
|
+ * - $memberId:付款人标识,会员为 member_id,代理为 AG{代理ID};
|
|
|
|
|
+ * - $extra:额外写入订单的字段;$orderPrefix:订单号前缀(代理为 ag)。
|
|
|
|
|
+ * 调用方需先校验支付公司启用、通道可用。成功时返回值带 order_no。
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function createPayOrder(string $model, $memberId, $amount, $paymentType, int $groupId, $channelConfig, array $extra = [], string $orderPrefix = ''): array
|
|
|
|
|
+ {
|
|
|
|
|
+ $result = [];
|
|
|
|
|
+ $result['chat_id'] = $memberId;
|
|
|
|
|
+ $result['code'] = 0;
|
|
|
|
|
+ $result['url'] = '';
|
|
|
$channel = ''; // 支付的通道
|
|
$channel = ''; // 支付的通道
|
|
|
$product = SanJinService::product($groupId);
|
|
$product = SanJinService::product($groupId);
|
|
|
$max = (float)($channelConfig->max ?? 0);
|
|
$max = (float)($channelConfig->max ?? 0);
|
|
@@ -298,11 +317,10 @@ class PaymentOrderService extends BaseService
|
|
|
$data['channel'] = $channel;
|
|
$data['channel'] = $channel;
|
|
|
$data['fee'] = $amount * $rate;
|
|
$data['fee'] = $amount * $rate;
|
|
|
$data['bank_name'] = $bankName;
|
|
$data['bank_name'] = $bankName;
|
|
|
- $order_no = self::createOrderNo('zm' . $data['type'] . '_', $memberId);
|
|
|
|
|
|
|
+ $order_no = self::createOrderNo($orderPrefix . 'zm' . $data['type'] . '_', $memberId);
|
|
|
$data['order_no'] = $order_no;
|
|
$data['order_no'] = $order_no;
|
|
|
$data['callback_url'] = ZimuPayService::getPayNotifyUrl();
|
|
$data['callback_url'] = ZimuPayService::getPayNotifyUrl();
|
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
|
- if ($bonusSnapshot !== null) $data['recharge_bonus_snapshot'] = $bonusSnapshot;
|
|
|
|
|
$data['status'] = self::STATUS_STAY;
|
|
$data['status'] = self::STATUS_STAY;
|
|
|
|
|
|
|
|
$ret = ZimuPayService::pay($amount, $order_no, (string)$memberId);
|
|
$ret = ZimuPayService::pay($amount, $order_no, (string)$memberId);
|
|
@@ -319,7 +337,8 @@ class PaymentOrderService extends BaseService
|
|
|
$data['pay_no'] = $item['orderNo'] ?? '';
|
|
$data['pay_no'] = $item['orderNo'] ?? '';
|
|
|
$data['pay_url'] = $payUrl;
|
|
$data['pay_url'] = $payUrl;
|
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
|
- static::$MODEL::create($data);
|
|
|
|
|
|
|
+ $model::create($data + $extra);
|
|
|
|
|
+ $result['order_no'] = $order_no;
|
|
|
|
|
|
|
|
if ($payUrl) {
|
|
if ($payUrl) {
|
|
|
$result['image'] = asset(self::createPaymentQrCode($payUrl));
|
|
$result['image'] = asset(self::createPaymentQrCode($payUrl));
|
|
@@ -347,11 +366,10 @@ class PaymentOrderService extends BaseService
|
|
|
$data['channel'] = $channel;
|
|
$data['channel'] = $channel;
|
|
|
$data['fee'] = $amount * $rate;
|
|
$data['fee'] = $amount * $rate;
|
|
|
$data['bank_name'] = $bankName;
|
|
$data['bank_name'] = $bankName;
|
|
|
- $order_no = self::createOrderNo('no' . $data['type'] . '_', $memberId);
|
|
|
|
|
|
|
+ $order_no = self::createOrderNo($orderPrefix . 'no' . $data['type'] . '_', $memberId);
|
|
|
$data['order_no'] = $order_no;
|
|
$data['order_no'] = $order_no;
|
|
|
$data['callback_url'] = NoPayService::getDepositNotifyUrl();
|
|
$data['callback_url'] = NoPayService::getDepositNotifyUrl();
|
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
|
- if ($bonusSnapshot !== null) $data['recharge_bonus_snapshot'] = $bonusSnapshot;
|
|
|
|
|
$data['status'] = self::STATUS_STAY;
|
|
$data['status'] = self::STATUS_STAY;
|
|
|
|
|
|
|
|
$ret = NoPayService::pay($amount, $order_no, (string)$memberId, $channel);
|
|
$ret = NoPayService::pay($amount, $order_no, (string)$memberId, $channel);
|
|
@@ -367,7 +385,8 @@ class PaymentOrderService extends BaseService
|
|
|
$data['status'] = self::STATUS_PROCESS;
|
|
$data['status'] = self::STATUS_PROCESS;
|
|
|
$data['pay_url'] = $payUrl;
|
|
$data['pay_url'] = $payUrl;
|
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
|
- static::$MODEL::create($data);
|
|
|
|
|
|
|
+ $model::create($data + $extra);
|
|
|
|
|
+ $result['order_no'] = $order_no;
|
|
|
|
|
|
|
|
if ($payUrl) {
|
|
if ($payUrl) {
|
|
|
$result['image'] = asset(self::createPaymentQrCode($payUrl));
|
|
$result['image'] = asset(self::createPaymentQrCode($payUrl));
|
|
@@ -395,11 +414,10 @@ class PaymentOrderService extends BaseService
|
|
|
$data['channel'] = $channel;
|
|
$data['channel'] = $channel;
|
|
|
$data['fee'] = $amount * $rate;
|
|
$data['fee'] = $amount * $rate;
|
|
|
$data['bank_name'] = $bankName;
|
|
$data['bank_name'] = $bankName;
|
|
|
- $order_no = self::createOrderNo('jd' . $data['type'] . '_', $memberId);
|
|
|
|
|
|
|
+ $order_no = self::createOrderNo($orderPrefix . 'jd' . $data['type'] . '_', $memberId);
|
|
|
$data['order_no'] = $order_no;
|
|
$data['order_no'] = $order_no;
|
|
|
$data['callback_url'] = JdPayService::getNotifyUrl();
|
|
$data['callback_url'] = JdPayService::getNotifyUrl();
|
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
|
- if ($bonusSnapshot !== null) $data['recharge_bonus_snapshot'] = $bonusSnapshot;
|
|
|
|
|
$data['status'] = self::STATUS_STAY;
|
|
$data['status'] = self::STATUS_STAY;
|
|
|
|
|
|
|
|
$ret = JdPayService::pay($amount, $order_no);
|
|
$ret = JdPayService::pay($amount, $order_no);
|
|
@@ -411,7 +429,8 @@ class PaymentOrderService extends BaseService
|
|
|
$data['pay_no'] = $item['orderNo'] ?? '';
|
|
$data['pay_no'] = $item['orderNo'] ?? '';
|
|
|
$data['pay_url'] = $payUrl;
|
|
$data['pay_url'] = $payUrl;
|
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
|
- static::$MODEL::create($data);
|
|
|
|
|
|
|
+ $model::create($data + $extra);
|
|
|
|
|
+ $result['order_no'] = $order_no;
|
|
|
|
|
|
|
|
if ($payUrl) {
|
|
if ($payUrl) {
|
|
|
$result['image'] = asset(self::createPaymentQrCode($payUrl));
|
|
$result['image'] = asset(self::createPaymentQrCode($payUrl));
|
|
@@ -438,11 +457,10 @@ class PaymentOrderService extends BaseService
|
|
|
$data['channel'] = $channel;
|
|
$data['channel'] = $channel;
|
|
|
$data['fee'] = $amount * $rate;
|
|
$data['fee'] = $amount * $rate;
|
|
|
$data['bank_name'] = SanJinService::getChannel($paymentType) ?? '';
|
|
$data['bank_name'] = SanJinService::getChannel($paymentType) ?? '';
|
|
|
- $order_no = self::createOrderNo('sj' . $data['type'] . '_', $memberId);
|
|
|
|
|
|
|
+ $order_no = self::createOrderNo($orderPrefix . 'sj' . $data['type'] . '_', $memberId);
|
|
|
$data['order_no'] = $order_no;
|
|
$data['order_no'] = $order_no;
|
|
|
$data['callback_url'] = SanJinService::getNotifyUrl();
|
|
$data['callback_url'] = SanJinService::getNotifyUrl();
|
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
$data['remark'] = '充值费率:' . $rate;
|
|
|
- if ($bonusSnapshot !== null) $data['recharge_bonus_snapshot'] = $bonusSnapshot;
|
|
|
|
|
$data['status'] = self::STATUS_STAY;
|
|
$data['status'] = self::STATUS_STAY;
|
|
|
$ret = SanJinService::pay(($amount * 100), $order_no, $channel);
|
|
$ret = SanJinService::pay(($amount * 100), $order_no, $channel);
|
|
|
Log::error('三斤支付发起:', $ret);
|
|
Log::error('三斤支付发起:', $ret);
|
|
@@ -455,7 +473,8 @@ class PaymentOrderService extends BaseService
|
|
|
$data['pay_no'] = $item['tradeNo'];
|
|
$data['pay_no'] = $item['tradeNo'];
|
|
|
$data['pay_url'] = $item['payUrl'];
|
|
$data['pay_url'] = $item['payUrl'];
|
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
$data['pay_data'] = json_encode($ret, JSON_UNESCAPED_UNICODE);
|
|
|
- $info = static::$MODEL::create($data);
|
|
|
|
|
|
|
+ $info = $model::create($data + $extra);
|
|
|
|
|
+ $result['order_no'] = $order_no;
|
|
|
// $text = "✅ 支付提示 \n";
|
|
// $text = "✅ 支付提示 \n";
|
|
|
$text = "{$data['bank_name']}充值确认 \n";
|
|
$text = "{$data['bank_name']}充值确认 \n";
|
|
|
// $text .= "支付方式:{$data['bank_name']} \n";
|
|
// $text .= "支付方式:{$data['bank_name']} \n";
|
|
@@ -481,7 +500,7 @@ class PaymentOrderService extends BaseService
|
|
|
public static function receivePay($params)
|
|
public static function receivePay($params)
|
|
|
{
|
|
{
|
|
|
if (ZimuPayService::getAppId() !== '' && ($params['appId'] ?? '') === ZimuPayService::getAppId()) {
|
|
if (ZimuPayService::getAppId() !== '' && ($params['appId'] ?? '') === ZimuPayService::getAppId()) {
|
|
|
- $info = self::findOne(['order_no' => $params['mchOrderNo'] ?? '']);
|
|
|
|
|
|
|
+ $info = self::findPayOrder((string)($params['mchOrderNo'] ?? ''));
|
|
|
if (!$info || $info->type != self::TYPE_PAY || !ZimuPayService::isRechargeChannel($info->channel)) {
|
|
if (!$info || $info->type != self::TYPE_PAY || !ZimuPayService::isRechargeChannel($info->channel)) {
|
|
|
Log::error('ZIMU充值回调订单不存在或类型不匹配', [
|
|
Log::error('ZIMU充值回调订单不存在或类型不匹配', [
|
|
|
'mch_order_no' => $params['mchOrderNo'] ?? '',
|
|
'mch_order_no' => $params['mchOrderNo'] ?? '',
|
|
@@ -526,7 +545,7 @@ class PaymentOrderService extends BaseService
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (NoPayService::getDepositMerchantId() !== '' && ($params['appId'] ?? '') === NoPayService::getDepositMerchantId()) {
|
|
if (NoPayService::getDepositMerchantId() !== '' && ($params['appId'] ?? '') === NoPayService::getDepositMerchantId()) {
|
|
|
- $info = self::findOne(['order_no' => $params['merchantOrderNo'] ?? '']);
|
|
|
|
|
|
|
+ $info = self::findPayOrder((string)($params['merchantOrderNo'] ?? ''));
|
|
|
if (!$info || $info->type != self::TYPE_PAY || !NoPayService::isRechargeChannel($info->channel)) {
|
|
if (!$info || $info->type != self::TYPE_PAY || !NoPayService::isRechargeChannel($info->channel)) {
|
|
|
Log::error('NO钱包充值回调订单不存在或类型不匹配', [
|
|
Log::error('NO钱包充值回调订单不存在或类型不匹配', [
|
|
|
'merchant_order_no' => $params['merchantOrderNo'] ?? '',
|
|
'merchant_order_no' => $params['merchantOrderNo'] ?? '',
|
|
@@ -571,8 +590,7 @@ class PaymentOrderService extends BaseService
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (($params['userCode'] ?? '') === JdPayService::getMerchantId()) {
|
|
if (($params['userCode'] ?? '') === JdPayService::getMerchantId()) {
|
|
|
- $info = self::findOne(['order_no' => $params['orderCode'] ?? ''])
|
|
|
|
|
- ?: static::$MODEL::where('pay_no', $params['orderCode'] ?? '')->first();
|
|
|
|
|
|
|
+ $info = self::findPayOrder((string)($params['orderCode'] ?? ''), true);
|
|
|
if (!$info || $info->type != self::TYPE_PAY) {
|
|
if (!$info || $info->type != self::TYPE_PAY) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -603,7 +621,7 @@ class PaymentOrderService extends BaseService
|
|
|
$must = ['mchId', 'productId', 'tradeNo', 'outTradeNo', 'amount', 'payAmount', 'state', 'createTime', 'payTime'];
|
|
$must = ['mchId', 'productId', 'tradeNo', 'outTradeNo', 'amount', 'payAmount', 'state', 'createTime', 'payTime'];
|
|
|
|
|
|
|
|
|
|
|
|
|
- $info = self::findOne(['order_no' => $params['outTradeNo']]);
|
|
|
|
|
|
|
+ $info = self::findPayOrder((string)($params['outTradeNo'] ?? ''));
|
|
|
if ($info) {
|
|
if ($info) {
|
|
|
// 平台以分计算转成元
|
|
// 平台以分计算转成元
|
|
|
$payAmount = $params['payAmount'] / 100;
|
|
$payAmount = $params['payAmount'] / 100;
|
|
@@ -648,10 +666,27 @@ class PaymentOrderService extends BaseService
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 按订单号找在线充值订单:ag 开头的是代理订单(agent_payment_orders),其余是会员订单。
|
|
|
|
|
+ * JD 回调的 orderCode 可能是三方单号,$byPayNo 时再按 pay_no 查。
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function findPayOrder(string $orderNo, bool $byPayNo = false): ?PaymentOrder
|
|
|
|
|
+ {
|
|
|
|
|
+ if ($orderNo === '') return null;
|
|
|
|
|
+ // 按 ag 前缀先查代理订单,找不到再查另一张表,避免前缀约定被打破时回调丢单。
|
|
|
|
|
+ $models = str_starts_with($orderNo, AgentPaymentOrder::ORDER_PREFIX)
|
|
|
|
|
+ ? [AgentPaymentOrder::class, PaymentOrder::class] : [PaymentOrder::class, AgentPaymentOrder::class];
|
|
|
|
|
+ $order = $models[0]::where('order_no', $orderNo)->first() ?: $models[1]::where('order_no', $orderNo)->first();
|
|
|
|
|
+ if (!$order && $byPayNo) {
|
|
|
|
|
+ $order = PaymentOrder::where('pay_no', $orderNo)->first() ?: AgentPaymentOrder::where('pay_no', $orderNo)->first();
|
|
|
|
|
+ }
|
|
|
|
|
+ return $order;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private static function applyPayCallback(PaymentOrder $info, $payAmount, string $status, string $successStatus, ?string $failStatus, array $params): bool
|
|
private static function applyPayCallback(PaymentOrder $info, $payAmount, string $status, string $successStatus, ?string $failStatus, array $params): bool
|
|
|
{
|
|
{
|
|
|
return DB::transaction(function () use ($info, $payAmount, $status, $successStatus, $failStatus, $params) {
|
|
return DB::transaction(function () use ($info, $payAmount, $status, $successStatus, $failStatus, $params) {
|
|
|
- $order = PaymentOrder::where('id', $info->id)->lockForUpdate()->first();
|
|
|
|
|
|
|
+ $order = $info::query()->where('id', $info->id)->lockForUpdate()->first();
|
|
|
if (!$order || (int)$order->type !== self::TYPE_PAY || !in_array((int)$order->status, self::PAY_OPEN_STATUSES, true)) {
|
|
if (!$order || (int)$order->type !== self::TYPE_PAY || !in_array((int)$order->status, self::PAY_OPEN_STATUSES, true)) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -663,6 +698,12 @@ class PaymentOrderService extends BaseService
|
|
|
$order->status = self::STATUS_SUCCESS;
|
|
$order->status = self::STATUS_SUCCESS;
|
|
|
$order->save();
|
|
$order->save();
|
|
|
|
|
|
|
|
|
|
+ if ($order instanceof AgentPaymentOrder) {
|
|
|
|
|
+ // 代理订单入代理钱包(合营计入保证金),不发充值优惠。
|
|
|
|
|
+ app(AgentPaymentService::class)->credit($order, (string)$payAmount, 'system', null);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
$wallet = WalletModel::where('member_id', $order->member_id)->lockForUpdate()->first();
|
|
$wallet = WalletModel::where('member_id', $order->member_id)->lockForUpdate()->first();
|
|
|
if (!$wallet) {
|
|
if (!$wallet) {
|
|
|
throw new Exception('钱包不存在', HttpStatus::CUSTOM_ERROR);
|
|
throw new Exception('钱包不存在', HttpStatus::CUSTOM_ERROR);
|
|
@@ -1440,10 +1481,15 @@ class PaymentOrderService extends BaseService
|
|
|
* @return {*}
|
|
* @return {*}
|
|
|
*/
|
|
*/
|
|
|
public static function singlePayOrder($id)
|
|
public static function singlePayOrder($id)
|
|
|
|
|
+ {
|
|
|
|
|
+ return self::queryPayOrder(self::findOne(['id' => $id]));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 向三方查询在线充值订单并按结果入账。会员和代理订单共用。 */
|
|
|
|
|
+ public static function queryPayOrder(?PaymentOrder $info): array
|
|
|
{
|
|
{
|
|
|
$msg = [];
|
|
$msg = [];
|
|
|
$msg['code'] = self::NOT;
|
|
$msg['code'] = self::NOT;
|
|
|
- $info = self::findOne(['id' => $id]);
|
|
|
|
|
if ($info && (int)$info->type === self::TYPE_PAY && in_array((int)$info->status, self::PAY_OPEN_STATUSES, true)) {
|
|
if ($info && (int)$info->type === self::TYPE_PAY && in_array((int)$info->status, self::PAY_OPEN_STATUSES, true)) {
|
|
|
if (NoPayService::isRechargeChannel($info->channel)) {
|
|
if (NoPayService::isRechargeChannel($info->channel)) {
|
|
|
$ret = NoPayService::queryPayOrder($info->order_no, (string)$info->member_id);
|
|
$ret = NoPayService::queryPayOrder($info->order_no, (string)$info->member_id);
|