Browse Source

完善支付回调和退款

dev
李可松 4 years ago
parent
commit
698da3a6c9
  1. 144
      app/Http/Controllers/Api/WxpayController.php

144
app/Http/Controllers/Api/WxpayController.php

@ -17,8 +17,6 @@ class WxpayController
//微信支付 支付结果通知网址
public function notify()
{
// {"sign": "3F99E6044C503B0E0131F95A1410B630", "appid": "wxb35ef055a4dd8ad4", "mch_id": "1606181693", "openid": "oBYj55W0gLv5MYUnsYUuJfzYzmsg", "cash_fee": "1", "fee_type": "CNY", "time_end": "20210623222330", "bank_type": "OTHERS", "nonce_str": "60d343d820e94", "total_fee": "1", "trade_type": "JSAPI", "result_code": "SUCCESS", "return_code": "SUCCESS", "is_subscribe": "N", "out_trade_no": "2842908479209865216", "transaction_id": "4200001210202106237487333085"}
$agent_id = request()->route('agent_id');
$agent = Agent::find($agent_id);
@ -31,16 +29,28 @@ class WxpayController
$app = Factory::payment($config);
try {
$response = $app->handlePaidNotify(function ($message, $fail) {
$this->log($message);
// 请求成功
if ($message['return_code'] === 'SUCCESS') {
//订单号带有pay_type后缀,主要是为了区分定金支付和尾款支付,前24位才是真正的订单号
//订单号带有status后缀,主要是为了区分定金支付和尾款支付,前24位才是真正的订单号
$order_no = substr($message['out_trade_no'], 0, 24);
$order = Order::query()
->where(['order_no' => $order_no])
->first();
//已经处理过的订单直接返回true
if ($order && in_array($order->status, [OrderStatus::PAID, OrderStatus::PAID_RETAINAGE])) {
if ($order && in_array($order->status, [OrderStatus::PAID, OrderStatus::PAID_RETAINAGE, OrderStatus::SUCCESS])) {
return true;
}
//判断该微信支付订单号有没有处理过
$exist_log = UserMoneyLog::where([
'user_id' => $order->user_id,
'order_id' => $order->id,
'type' => 1,
'transaction_id' => $message['transaction_id'],
])->first();
if ($exist_log) {
return true;
}
@ -50,18 +60,21 @@ class WxpayController
try {
$status = $order->status;
$pay_type = $order->pay_type;
$money = $message['total_fee'] / 100;
//定金支付和首付款支付
if (in_array($pay_type, [1, 2])) {
if ($pay_type == OrderStatus::UNPAID) {
if ($status == OrderStatus::UNPAID) {
$order->status = OrderStatus::PAY_EARNEST;
} else if ($status == OrderStatus::PAY_EARNEST) {
$order->status = OrderStatus::PAID_RETAINAGE;
//只有支付的金额大于等于订单总价,才将订单状态修改为PAID_RETAINAGE
if ($order->paid_money + $money >= $order->price) {
$order->status = OrderStatus::PAID_RETAINAGE;
}
}
} else if ($pay_type == 0) {
$order->status = OrderStatus::PAID;
}
$money = $message['total_fee'] / 100;
$order->paid_at = time();
$order->paid_money = DB::raw('`paid_money` + ' . $money);
$order->save();
@ -81,7 +94,8 @@ class WxpayController
'money' => -$money,
'order_id' => $order->id,
'type' => 1,
'desc' => '购买产品:' . $order->title,
'desc' => DB::raw("LEFT('购买产品:{$order->title}', 250)"),
'transaction_id' => $message['transaction_id'], //微信支付订单号
'created_at' => time(), //模型没有updated_at,无法自动写入时间
]);
@ -98,14 +112,10 @@ class WxpayController
}
// 希望微信重试
$fail('Order not exists.');
$fail('Unknown error 2');
});
} catch (InvalidSignException | Exception $e) {
$time = time();
$filename = storage_path('logs/wxpay_notify_') . date('Y-m-d-H', $time) . '.log';
$data = '[' . date('Y-m-d H:i:s', $time) . ']' . PHP_EOL;
$data .= '[message]:' . $e->getMessage() . $e->getFile() . $e->getLine() . PHP_EOL . PHP_EOL;
file_put_contents($filename, $data, FILE_APPEND);
$this->log($e->getMessage() . $e->getFile() . $e->getLine());
return 'error';
}
@ -115,9 +125,6 @@ class WxpayController
//退款通知
public function refund()
{
// {"sign": "3F99E6044C503B0E0131F95A1410B630", "appid": "wxb35ef055a4dd8ad4", "mch_id": "1606181693", "openid": "oBYj55W0gLv5MYUnsYUuJfzYzmsg", "cash_fee": "1", "fee_type": "CNY", "time_end": "20210623222330", "bank_type": "OTHERS", "nonce_str": "60d343d820e94", "total_fee": "1", "trade_type": "JSAPI", "result_code": "SUCCESS", "return_code": "SUCCESS", "is_subscribe": "N", "out_trade_no": "2842908479209865216", "transaction_id": "4200001210202106237487333085"}
$agent_id = request()->route('agent_id');
$agent = Agent::find($agent_id);
@ -131,43 +138,81 @@ class WxpayController
try {
$response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
// 记录一下本地调试
file_put_contents(storage_path('/wxpay/refund' . date('Y-m-d-H') . '.log'), date('Y-m-d H:i:s') . PHP_EOL . json_encode($message) . PHP_EOL . json_encode($reqInfo), FILE_APPEND);
$this->log(['message' => $message, 'reqInfo' => $reqInfo], 'refund');
/*$reqInfo = [
'out_refund_no' => '131811191610442717309',
'out_trade_no' => '20210722164514946742983',
'refund_account' => 'REFUND_SOURCE_RECHARGE_FUNDS',
'refund_fee' => 8800,
'refund_id' => '50000408942018111907145868882',
'refund_recv_accout' => '支付用户零钱',
'refund_request_source' => 'API',
'refund_status' => 'SUCCESS',
'settlement_refund_fee' => 8800,
'settlement_total_fee' => 8800,
'success_time' => date('Y-m-d H:i:s'),
'total_fee' => 8800,
'transaction_id' => '1004400740201409030005092168',
];*/
// 请求成功
if ($message['return_code'] === 'SUCCESS') {
//订单号带有pay_type后缀,主要是为了区分定金支付和尾款支付,前24位才是真正的订单号
$order_no = substr($message['out_trade_no'], 0, 24);
//订单号带有status后缀,主要是为了区分定金支付和尾款支付,前24位才是真正的订单号
$order_no = substr($reqInfo['out_trade_no'], 0, 24);
$order = Order::query()
->where(['order_sn' => $order_no])
->where(['order_no' => $order_no])
->first();
// 退款成功
if ($reqInfo['refund_status'] === 'SUCCESS') {
DB::beginTransaction();
try {
//如果已经处理过则不再处理
if ($order->status == OrderStatus::REFUNDED) {
return true;
}
$apply = RefundApply::query()
->where('refund_sn', $reqInfo['out_refund_no'])
->first();
//如果已经存在相关的退款记录,也不再处理
$exist_log = UserMoneyLog::where([
'user_id' => $order->user_id,
'order_id' => $order->id,
'type' => 2,
'transaction_id' => $reqInfo['transaction_id'],
])->first();
if ($exist_log) {
return true;
}
if (!$apply) {
$fail('退款单没找到');
}
$log = UserMoneyLog::query()
->where([
'user_id' => $order->user_id,
'order_id' => $order->id,
'type' => 1,
'transaction_id' => $reqInfo['transaction_id'],
])->first();
$apply->state = 2;
$apply->save();
if (!$log) {
$fail('找不到交易信息');
}
$order->state = UserGoodsOrder::REFUNDED;
// 退款成功
if ($reqInfo['refund_status'] === 'SUCCESS') {
DB::beginTransaction();
try {
//更新订单状态为退款成功
$order->status = OrderStatus::REFUNDED;
$order->save();
//记录日志
UserMoneyLog::create([
'user_id' => $order->user_id,
'agent_id' => $order->agent_id,
'money' => $reqInfo['settlement_refund_fee'] / 100,
'order_id' => $order->id,
'type' => 2,
'desc' => DB::raw("LEFT('退款:{$order->title}', 250)"),
'transaction_id' => $reqInfo['transaction_id'],
'created_at' => time(),
]);
// 退库存
GoodsSpecs::query()
->where([
'id' => $order->goods_specs_id,
'goods_id' => $order->goods_id,
])
->update([
'stock' => DB::raw('stock+' . $order->number . ''),
]);
Product::query()
->where('id', $order->product_id)
->increment('stock', $order->num);
DB::commit();
return true;
@ -178,7 +223,7 @@ class WxpayController
}
}
$fail('Unknown error');
$fail('Unknown error 2');
});
} catch (Exception $e) {
return 'error';
@ -186,4 +231,17 @@ class WxpayController
return $response;
}
//保存消息,用于调试
private function log($write_data, $type = 'notify')
{
$dir = storage_path('wxpay');
if (!is_dir($dir)) {
mkdir($dir);
}
$filename = $dir . '/' . $type . '_' . date('Y-m-d-H') . '.log';
$data = '[' . date('Y-m-d H:i:s') . ']' . PHP_EOL;
$data .= '[message]: ' . (is_array($write_data) ? json_encode($write_data) : $write_data) . PHP_EOL . PHP_EOL;
file_put_contents($filename, $data, FILE_APPEND);
}
}
Loading…
Cancel
Save