You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yanzong/app/common/service/order/Refund.php

142 lines
5.1 KiB

11 months ago
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\common\service\order;
use app\common\model\Payment as PaymentModel;
use app\common\model\PaymentTrade as PaymentTradeModel;
use app\common\model\User as UserModel;
use app\common\model\user\BalanceLog as BalanceLogModel;
use app\common\service\BaseService;
use app\common\enum\payment\Method as PaymentMethodEnum;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
use app\common\library\payment\Facade as PaymentFacade;
use cores\exception\BaseException;
/**
* 订单退款服务类
* Class Refund
* @package app\common\service\order
*/
class Refund extends BaseService
{
/**
* 执行订单退款
* @param mixed $order 订单信息
* @param string|null $money 退款金额
* @return bool
* @throws \cores\exception\BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function handle($order, ?string $money = null): bool
{
// 退款金额,如不指定则默认为订单实付款金额
is_null($money) && $money = (string)$order['pay_price'];
if ($money == 0) {
return true;
}
// 余额支付退款
if ($order['pay_method'] === PaymentMethodEnum::BALANCE) {
return $this->balance($order, $money);
}
// 第三方支付退款
if (in_array($order['pay_method'], [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY])) {
return $this->payment($order, $money);
}
return false;
}
/**
* 余额支付退款
* @param mixed $order 订单信息
* @param string $money 退款金额
* @return bool
*/
private function balance($order, string $money): bool
{
// 回退用户余额
UserModel::setIncBalance((int)$order['user_id'], (float)$money);
// 记录余额明细
BalanceLogModel::add(SceneEnum::REFUND, [
'user_id' => $order['user_id'],
'money' => $money,
], ['order_no' => $order['order_no']], $order['store_id']);
return true;
}
/**
* 第三方支付退款
* @param mixed $order 订单信息
* @param string $money 退款金额
* @return bool
* @throws BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function payment($order, string $money): bool
{
// 获取第三方交易记录
$tradeInfo = $this->getTradeInfo($order['trade_id']);
// 获取支付方式的配置信息
$options = $this->getPaymentConfig($order);
// 构建支付模块
$Payment = PaymentFacade::store($order['pay_method'])->setOptions($options, $order['platform']);
// 执行第三方支付下单API
if (!$Payment->refund($tradeInfo['out_trade_no'], $money, ['totalFee' => (string)$order['pay_price']])) {
throwError($Payment->getError() ?: '第三方支付退款API调用失败');
}
// 将第三方交易记录更新为已退款状态
$this->updateTradeState($order['trade_id']);
return true;
}
/**
* 获取第三方交易记录
* @param int $tradeId 交易记录ID
* @return PaymentTradeModel|null
* @throws BaseException
*/
private function getTradeInfo(int $tradeId): ?PaymentTradeModel
{
$tradeInfo = PaymentTradeModel::detail($tradeId);
empty($tradeInfo) && throwError('未找到第三方交易记录');
return $tradeInfo;
}
/**
* 将第三方交易记录更新为已退款状态
* @param int $tradeId 交易记录ID
*/
private function updateTradeState(int $tradeId)
{
PaymentTradeModel::updateToRefund($tradeId);
}
/**
* 获取支付方式的配置信息
* @param mixed $order 订单信息
* @return mixed
* @throws BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getPaymentConfig($order)
{
$PaymentModel = new PaymentModel;
$templateInfo = $PaymentModel->getPaymentInfo($order['pay_method'], $order['platform'], $order['store_id']);
return $templateInfo['template']['config'][$order['pay_method']];
}
}