|
@@ -5,13 +5,20 @@ namespace app\admin\controller\order;
|
|
|
use app\admin\validate\order\ReturnValidate;
|
|
|
use app\controller\Curd;
|
|
|
use app\model\GoodsComponent;
|
|
|
+use app\model\MemberAccount;
|
|
|
use app\model\Order;
|
|
|
use app\model\OrderExpress;
|
|
|
use app\model\OrderReturn;
|
|
|
use app\model\OrderSheet;
|
|
|
+use app\model\PayDetail;
|
|
|
+use Payment\Common\PayException;
|
|
|
+use support\Db;
|
|
|
use support\exception\BusinessException;
|
|
|
+use support\Log;
|
|
|
use support\Request;
|
|
|
use support\Response;
|
|
|
+use Tinywan\Jwt\JwtToken;
|
|
|
+use Yansongda\Pay\Pay;
|
|
|
|
|
|
class RefundController extends Curd
|
|
|
{
|
|
@@ -200,19 +207,270 @@ class RefundController extends Curd
|
|
|
|
|
|
public function customRefund(Request $request)
|
|
|
{
|
|
|
- $orderId = $request->post('order_id','');
|
|
|
$orderId = $request->post('order_id', '');
|
|
|
$amount = $request->post('refund_amount', 0);
|
|
|
$password = $request->post('refund_password', '');
|
|
|
+ $remark = $request->post('refund_remark', '');
|
|
|
if (!$orderId || !$amount || !$password) {
|
|
|
return json_fail('参数异常');
|
|
|
}
|
|
|
if ($password != '123456') {
|
|
|
return json_fail('支付密码错误');
|
|
|
}
|
|
|
- $order = Order::where('order_id',$orderId)->where('order_status_payment','SUCCESS')->first();
|
|
|
- if (!$order){
|
|
|
+ $order = Order::where('order_id', $orderId)->where('order_status_payment', 'SUCCESS')->first();
|
|
|
+ if (!$order) {
|
|
|
return json_fail("订单异常");
|
|
|
}
|
|
|
+ if ($amount > $order->order_amount_pay) {
|
|
|
+ return json_fail("退款金额不可超过支付金额");
|
|
|
+ }
|
|
|
+ $payDetail = PayDetail::where('join_pay_order_id', $order->order_groupby)
|
|
|
+ ->where('pay_status', 'SUCCESS')
|
|
|
+ ->whereIn('pay_category', ['GOODS', 'SERVICE', 'CHNMED', 'CHNNCD', 'MEALS', 'DISHES', 'VIP', 'PACKAGE'])
|
|
|
+ ->get()
|
|
|
+ ->toArray();
|
|
|
+ if (empty($payDetail)) {
|
|
|
+ return json_fail("支付状态异常");
|
|
|
+ }
|
|
|
+ $response = [];
|
|
|
+ Db::beginTransaction();
|
|
|
+ try {
|
|
|
+ // 主订单,退款作为优惠入库
|
|
|
+ $this->updateMainOrderByRefund($order, $amount, $remark);
|
|
|
+ // return 表记录
|
|
|
+ $returnId = $this->createReturnRecord($order, $amount);
|
|
|
+
|
|
|
+ // 组合支付,退到余额账户
|
|
|
+ $prepayid = '';
|
|
|
+ if (count($payDetail) > 1) {
|
|
|
+ $prepayid = $order->join_order_member_id . '-CASH';
|
|
|
+ $this->refundToCash($order->join_order_member_id, $amount);
|
|
|
+ $response = ['order_id' => $order->order_id, 'member_id' => $order->join_order_member_id];
|
|
|
+ } else if (count($payDetail) == 1) {
|
|
|
+ $payDetail0 = $payDetail[0];
|
|
|
+ $payWay = explode('-', $payDetail0['pay_prepayid']);
|
|
|
+ if ($payWay[0] == 'WXPAY') {
|
|
|
+ $prepayid = 'WXPAY';
|
|
|
+ $response = $this->refundToWx($payDetail0, $returnId, $amount);
|
|
|
+ } elseif ($payWay[0] == 'ALIPAY') {
|
|
|
+ $prepayid = 'WXPAY';
|
|
|
+ $response = $this->refundToAlipay($payDetail0, $amount);
|
|
|
+ } elseif (isset($payWay[1]) && $payWay[1] == 'CASH'){
|
|
|
+ $prepayid = $order->join_order_member_id . '-CASH';
|
|
|
+ $this->refundToCash($order->join_order_member_id, $amount);
|
|
|
+ $response = ['order_id' => $order->order_id, 'member_id' => $order->join_order_member_id];
|
|
|
+ } elseif (isset($payWay['1']) && $payWay[1] == 'CARD'){
|
|
|
+ $prepayid = $order->join_order_member_id . '-CASH';
|
|
|
+ $this->refundToCard($order->join_order_member_id, $amount);
|
|
|
+ $response = ['order_id' => $order->order_id, 'member_id' => $order->join_order_member_id];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // payDetail 表记录
|
|
|
+ $this->createReturnPayDetail($order, $prepayid, $amount, $response);
|
|
|
+
|
|
|
+ Db::commit();
|
|
|
+
|
|
|
+ return json_success('success');
|
|
|
+ } catch (BusinessException $e) {
|
|
|
+ Db::rollBack();
|
|
|
+ return json_fail($e->getMessage());
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Db::rollBack();
|
|
|
+ return json_fail("退款失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Desc 退款到余额
|
|
|
+ * @Author Gorden
|
|
|
+ * @Date 2024/8/20 11:54
|
|
|
+ *
|
|
|
+ * @param $memberId
|
|
|
+ * @param $amount
|
|
|
+ * @return void
|
|
|
+ * @throws BusinessException
|
|
|
+ */
|
|
|
+ private function refundToCash($memberId, $amount)
|
|
|
+ {
|
|
|
+ $account = MemberAccount::where('join_account_member_id', $memberId)->where('member_account_classify', 'CASH')->first();
|
|
|
+ if (!$account) {
|
|
|
+ throw new BusinessException("余额账户异常");
|
|
|
+ }
|
|
|
+ $account->member_account_surplus = $account->member_account_surplus + $amount;
|
|
|
+ $account->save();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Desc 退款到储蓄卡
|
|
|
+ * @Author Gorden
|
|
|
+ * @Date 2024/8/20 14:47
|
|
|
+ *
|
|
|
+ * @param $memberId
|
|
|
+ * @param $amount
|
|
|
+ * @return void
|
|
|
+ * @throws BusinessException
|
|
|
+ */
|
|
|
+ private function refundToCard($cardNbr, $amount)
|
|
|
+ {
|
|
|
+ $account = MemberAccount::where('member_account_nbr', $cardNbr)->where('member_account_classify', 'CARD')->first();
|
|
|
+ if (!$account) {
|
|
|
+ throw new BusinessException("储值卡账户异常");
|
|
|
+ }
|
|
|
+ $account->member_account_surplus = $account->member_account_surplus + $amount;
|
|
|
+ $account->save();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Desc
|
|
|
+ * @Author Gorden
|
|
|
+ * @Date 2024/8/20 14:17
|
|
|
+ *
|
|
|
+ * @param $params
|
|
|
+ * @param $returnId
|
|
|
+ * @param $amount
|
|
|
+ * @return mixed
|
|
|
+ * @throws BusinessException
|
|
|
+ * @throws \Yansongda\Pay\Exceptions\GatewayException
|
|
|
+ * @throws \Yansongda\Pay\Exceptions\InvalidArgumentException
|
|
|
+ * @throws \Yansongda\Pay\Exceptions\InvalidSignException
|
|
|
+ */
|
|
|
+ private function refundToWx($params, $returnId, $amount)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ $data = [
|
|
|
+ 'type' => 'app',
|
|
|
+ 'out_trade_no' => $params['join_pay_order_id'],
|
|
|
+ 'out_refund_no' => $returnId,
|
|
|
+ 'total_fee' => $params['pay_amount'] * 100,
|
|
|
+ 'refund_fee' => $amount * 100,
|
|
|
+ 'refund_desc' => '退款',
|
|
|
+ ];
|
|
|
+ $res = Pay::wechat(config('payment.wxpay'))->refund($data);
|
|
|
+ $resArray = json_decode($res, true);
|
|
|
+ if (!$resArray['result_code'] == 'SUCCESS' || !$resArray['return_code'] == 'SUCCESS') {
|
|
|
+ Log::channel('pay')->error('WXPAY_REFUND_FAIL', $resArray);
|
|
|
+ throw new BusinessException("退款失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ return $resArray;
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ throw new BusinessException("退款失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Desc 支付宝退款
|
|
|
+ * @Author Gorden
|
|
|
+ * @Date 2024/8/20 14:40
|
|
|
+ *
|
|
|
+ * @param $params
|
|
|
+ * @param $amount
|
|
|
+ * @return mixed
|
|
|
+ * @throws BusinessException
|
|
|
+ */
|
|
|
+ private function refundToAlipay($params, $amount)
|
|
|
+ {
|
|
|
+ $data = [
|
|
|
+ 'out_trade_no' => $params['join_pay_order_id'],
|
|
|
+ 'refund_amount' => $amount,
|
|
|
+ ];
|
|
|
+ try {
|
|
|
+ $res = Pay::alipay(config('payment.alipay'))->refund($data);
|
|
|
+ $resArray = json_decode($res, true);
|
|
|
+ if ($resArray['fund_change'] != 'Y' || $resArray['msg'] != 'Success') {
|
|
|
+ Log::channel('pay')->error('ALIPAY_REFUND_FAIL', $resArray);
|
|
|
+ throw new BusinessException("退款失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ return $resArray;
|
|
|
+ }catch (\Exception $e){
|
|
|
+
|
|
|
+ throw new BusinessException("退款失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Desc 更新主订单
|
|
|
+ * @Author Gorden
|
|
|
+ * @Date 2024/8/20 14:56
|
|
|
+ *
|
|
|
+ * @param $order
|
|
|
+ * @param $amount
|
|
|
+ * @param $remark
|
|
|
+ * @return void
|
|
|
+ * @throws BusinessException
|
|
|
+ */
|
|
|
+ private function updateMainOrderByRefund($order, $amount, $remark)
|
|
|
+ {
|
|
|
+ $orderDiscountJson = [];
|
|
|
+ if (!empty($order->order_discount_json)) {
|
|
|
+ $orderDiscountJson = json_decode($order->order_discount_json, true);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ $orderDiscountJson[date('YH:i:s H:i:s')] = [
|
|
|
+ 'coupon_id' => null,
|
|
|
+ 'coupon_value' => $amount,
|
|
|
+ 'coupon_classify' => '退款',
|
|
|
+ 'coupon_detail_id' => $remark
|
|
|
+ ];
|
|
|
+
|
|
|
+ $order->order_discount_json = json_encode($orderDiscountJson, JSON_UNESCAPED_UNICODE);
|
|
|
+ $order->order_amount_pay = $order->order_amount_pay - $amount;
|
|
|
+ $order->save();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ throw new BusinessException("退款失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Desc
|
|
|
+ * @Author Gorden
|
|
|
+ * @Date 2024/8/20 13:51
|
|
|
+ *
|
|
|
+ * @param $order
|
|
|
+ * @return int
|
|
|
+ * @throws BusinessException
|
|
|
+ */
|
|
|
+ private function createReturnRecord($order, $amount)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ return OrderReturn::insertGetId([
|
|
|
+ 'join_order_return_user_id' => JwtToken::getCurrentId(),
|
|
|
+ 'join_return_member_id' => $order->join_order_member_id,
|
|
|
+ 'join_return_order_id' => $order->order_id,
|
|
|
+ 'order_return_status' => 'DONE',
|
|
|
+ 'order_return_category' => '退款',
|
|
|
+ 'order_return_apply_datetime' => date('Y-m-d H:i:s'),
|
|
|
+ 'order_return_apply_json' => json_encode(['reason' => '后台自定义退款']),
|
|
|
+ 'order_return_accept_datetime' => date('Y-m-d H:i:s'),
|
|
|
+ 'order_return_refund_json' => json_encode(['amount' => $amount, 'user_id' => JwtToken::getCurrentId(), 'datetime' => date('Y-m-d H:i:s')]),
|
|
|
+ 'order_return_addtimes' => time()
|
|
|
+ ]);
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ throw new BusinessException("创建退款信息失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private function createReturnPayDetail($order, $prepayid, $amount, $response = [])
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ return PayDetail::insert([
|
|
|
+ 'join_pay_member_id' => $order->join_order_member_id,
|
|
|
+ 'join_pay_order_id' => $order->order_groupby,
|
|
|
+ 'pay_status' => 'SUCCESS',
|
|
|
+ 'pay_category' => 'REFUND',
|
|
|
+ 'pay_amount' => $amount,
|
|
|
+ 'pay_paytimes' => date('Y-m-d H:i:s'),
|
|
|
+ 'pay_prepayid' => $prepayid,
|
|
|
+ 'pay_json_request' => json_encode(['order_id' => $order->order_id]),
|
|
|
+ 'pay_json_response' => json_encode($response),
|
|
|
+ 'pay_addtimes' => time()
|
|
|
+ ]);
|
|
|
+ } catch (\Exception $e) {
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
}
|