扣款失败后,重试扣款
This commit is contained in:
parent
6f331a22d5
commit
ce08f7866d
|
@ -65,7 +65,7 @@ class AgreementPaySendSms extends Command
|
|||
// 开始发送扣款短信
|
||||
$res = AliSms::sendSms(['phone_numbers' => $collection->mobile], 3);
|
||||
$redis->set($cacheKey, true, 'ex', $cacheKeys['ttl']);
|
||||
if ($res['code'] == "OK") {
|
||||
if ($res['code'] == 200) {
|
||||
$this->successCount += 1;
|
||||
$output->writeln("短信发送受理成功");
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace app\cmd;
|
||||
|
||||
use app\model\Order;
|
||||
use app\model\Sign;
|
||||
use app\service\AgreementService;
|
||||
use think\Collection;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use think\facade\Log;
|
||||
|
||||
class PayOrderRetry extends Command
|
||||
{
|
||||
protected int $count = 0;
|
||||
protected int $successCount = 0;
|
||||
protected int $failedCount = 0;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('PayOrderRetry')->setDescription('重试扣款失败的订单');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有失败订单每天重试一次,重试到订单创建时间的月底。如果还是失败就进行解约操作
|
||||
* 每天11点执行
|
||||
* @param Input $input
|
||||
* @param Output $output
|
||||
* @return void
|
||||
*/
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 本月内的支付失败订单
|
||||
// 获取本月的开始时间
|
||||
$startOfMonth = new \DateTime('first day of this month 00:00:00');
|
||||
$startOfMonthFormatted = $startOfMonth->format('Y-m-d H:i:s');
|
||||
|
||||
// 获取本月的结束时间
|
||||
$endOfMonth = new \DateTime('last day of this month 23:59:59');
|
||||
$endOfMonthFormatted = $endOfMonth->format('Y-m-d H:i:s');
|
||||
|
||||
Order::where(['pay_status' => Order::PAY_STATUS_FAIL])->whereBetweenTime('create_time', strtotime($startOfMonthFormatted), strtotime($endOfMonthFormatted))
|
||||
->where(['is_retry' => Order::RETRY_STATUS_NO])
|
||||
->field('id,order_number,agreement_id,user_id')->chunk(100, function (Collection $orderCollection) use (&$output) {
|
||||
// 拉取支付失败的订单
|
||||
foreach ($orderCollection as $order) {
|
||||
// 查询签约状态是否取消
|
||||
$signInfo = Sign::getByAgreementId($order->agreement_id);
|
||||
if ($signInfo->isEmpty() || $signInfo->sign_status != Order::STATUS_SIGNED) {
|
||||
continue;
|
||||
}
|
||||
$res = AgreementService::RetryPayOrder($order->order_number, $signInfo->agreement_id);
|
||||
if ($res['respCode'] == 1000) {
|
||||
$this->successCount += 1;
|
||||
$output->writeln("受理成功,等待支付通知");
|
||||
} else {
|
||||
$this->failedCount += 1;
|
||||
$output->writeln("用户" . $order->user_id . "扣款失败:" . $res['respMsg']);
|
||||
}
|
||||
}
|
||||
});
|
||||
Log::info(sprintf("扣款job执行情况:执行成功,累计 %s, 受理成功 %s, 失败 %s", $this->count, $this->successCount, $this->failedCount));
|
||||
$output->writeln(sprintf("重试扣款失败的订单执行成功,累计 %s, 受理成功 %s, 失败 %s", $this->count, $this->successCount, $this->failedCount));
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace app\front;
|
||||
|
||||
use app\config\ResponseCode;
|
||||
use app\service\CmbService;
|
||||
use app\service\OrderService;
|
||||
use app\service\RechargeService;
|
||||
|
@ -12,7 +11,11 @@ class Order extends Base
|
|||
{
|
||||
public function list(Request $request): \think\Response
|
||||
{
|
||||
if (empty($request->user_id)) {
|
||||
return responseOk();
|
||||
}
|
||||
$params['user_id'] = $request->user_id;
|
||||
$params['is_retry'] = \app\model\Order::RETRY_STATUS_NO;
|
||||
return responseOk(app()->make(OrderService::class)->list($params));
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@ class Order extends BaseModel
|
|||
const REFUND_STATUS_WAIT = 1;
|
||||
const REFUND_STATUS_SUCCESS = 2;
|
||||
const REFUND_STATUS_FAIL = 3;
|
||||
// 重试状态
|
||||
const RETRY_STATUS_NO = 0; // 未重试
|
||||
const RETRY_STATUS_YES = 1; // 已重试
|
||||
|
||||
const STATUS_TEXT = [
|
||||
self::STATUS_WAIT_SIGN => '待签约',
|
||||
|
|
|
@ -216,6 +216,68 @@ class AgreementService extends BaseService
|
|||
return CmbHttpUtils::doPost($funcName, $requestParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扣款失败,重试
|
||||
*
|
||||
* @param string $orderNumber
|
||||
* @param string $agreementId
|
||||
* @return array|mixed|string
|
||||
*/
|
||||
public static function RetryPayOrder(string $orderNumber, string $agreementId)
|
||||
{
|
||||
// 判断订单状态是否正确
|
||||
$order = Order::getByOrderNumber($orderNumber);
|
||||
if ($order->isEmpty() || $order->pay_status != Order::PAY_STATUS_FAIL || $order->is_retry == Order::RETRY_STATUS_YES) {
|
||||
return ['respCode' => 1000, 'respMsg' => '处理成功'];
|
||||
}
|
||||
|
||||
// 处理订单再次扣款
|
||||
// 创建新的订单
|
||||
$productId = $order->product_id;
|
||||
$product = Product::getBySupplierProductId($productId);
|
||||
$newOrder = [
|
||||
'user_id' => $order->user_id,
|
||||
'order_number' => StringUtil::makeOrderNumber(),
|
||||
'account' => $order->account,
|
||||
'type' => $order->type,
|
||||
'product_id' => $order->product_id,
|
||||
'price' => $order->price,
|
||||
'bonus' => $order->bonus,
|
||||
'agreement_id' => $order->agreement_id,
|
||||
'order_status' => Order::STATUS_SIGNED
|
||||
];
|
||||
|
||||
// 生成重试订单
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 创建新订单
|
||||
Order::create($newOrder);
|
||||
// 更新老订单
|
||||
$order->is_retry = Order::RETRY_STATUS_YES;
|
||||
$order->retry_order_num = $newOrder['order_number'];
|
||||
$res = $order->save();
|
||||
if (!$res) {
|
||||
throw new \Exception("重试支付,更新老订单失败,订单号:" . $orderNumber);
|
||||
}
|
||||
Db::commit();
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
Log::error("Job:PayOrderRetry,错误信息:" . $e->getMessage());
|
||||
return ['respCode' => 1001, 'respMsg' => $e->getMessage()];
|
||||
}
|
||||
|
||||
// 扣款参数
|
||||
$requestParams = [
|
||||
'agreementId' => $agreementId,
|
||||
'billNo' => $newOrder['order_number'],
|
||||
'amount' => $newOrder['price'] * 100,
|
||||
'notifyUrl' => config('cmb.pay_notify_url'),
|
||||
'productName' => $product['name']
|
||||
];
|
||||
$funcName = 'agreementPay';
|
||||
return CmbHttpUtils::doPost($funcName, $requestParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 协议扣款回调处理
|
||||
* @param array $data
|
||||
|
@ -252,6 +314,10 @@ class AgreementService extends BaseService
|
|||
if ($encryptData['result'] == 2) {
|
||||
RechargeService::rechargeOrder($orderNumber); // 支付成功,到直连天下充值
|
||||
}
|
||||
// 支付失败
|
||||
if ($encryptData['result'] == 3 && BaseService::isLastDayOfMonth()) {
|
||||
CmbService::releaseMerchant($order->agreement_id);
|
||||
}
|
||||
if ($res) {
|
||||
return ['respCode' => 1000, 'respMsg' => '处理成功'];
|
||||
} else {
|
||||
|
|
|
@ -44,14 +44,14 @@ class BaseService
|
|||
$file = $data['file'];
|
||||
$basePath = config('filesystem.disks.public.root');
|
||||
validate(['file' => ['fileExt:jpg,png,jpeg,bmp,xlsx,xls,webp|fileSize:20*1024*1024']])->check($data);
|
||||
$path = '/images/'.date('Y').'/'.date('m').'/'.date('d');
|
||||
$fullPath = $basePath.$path;
|
||||
if(!file_exists($fullPath)) {
|
||||
mkdir($fullPath,0777,true);
|
||||
$path = '/images/' . date('Y') . '/' . date('m') . '/' . date('d');
|
||||
$fullPath = $basePath . $path;
|
||||
if (!file_exists($fullPath)) {
|
||||
mkdir($fullPath, 0777, true);
|
||||
}
|
||||
$imagePath = Filesystem::putFile($path,$file,'md5');
|
||||
$imagePath = str_replace('\\','/',$imagePath);
|
||||
return ['image_path' =>config('filesystem.disks.public.url').$imagePath ];
|
||||
$imagePath = Filesystem::putFile($path, $file, 'md5');
|
||||
$imagePath = str_replace('\\', '/', $imagePath);
|
||||
return ['image_path' => config('filesystem.disks.public.url') . $imagePath];
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
|
@ -59,4 +59,14 @@ class BaseService
|
|||
//找不到方法,自动调用模型中基类方法
|
||||
return call_user_func_array([$this->model, $name], $arguments);
|
||||
}
|
||||
|
||||
public static function isLastDayOfMonth()
|
||||
{
|
||||
$date = date('Y-m-d');
|
||||
// 获取该月的最后一天
|
||||
$lastDayOfMonth = date('Y-m-t', strtotime($date));
|
||||
|
||||
// 比较给定日期和该月的最后一天
|
||||
return $date === $lastDayOfMonth;
|
||||
}
|
||||
}
|
|
@ -167,7 +167,8 @@ class CmbService extends BaseService
|
|||
if ($res['result'] == 2) { // 扣款成功
|
||||
RechargeService::rechargeOrder($orderNumber);
|
||||
}
|
||||
if ($res['result'] == 3) { // 扣款失败 解约
|
||||
// 月底不进行重试,失败直接解约
|
||||
if ($res['result'] == 3 && BaseService::isLastDayOfMonth()) { // 扣款失败 解约
|
||||
self::releaseMerchant($order->agreement_id);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -25,7 +25,7 @@ class OrderService extends BaseService
|
|||
|
||||
public function list($params)
|
||||
{
|
||||
return $this->model->searchPages(['order_number', 'type', 'status', 'pay_status', 'create_at', 'user_id'], $params)->toArray();
|
||||
return $this->model->searchPages(['order_number', 'type', 'status', 'create_at', 'user_id', 'is_retry'], $params)->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,8 @@ return [
|
|||
'getPayOrder' => \app\cmd\GetPayOrder::class,
|
||||
'getRefundOrder' => \app\cmd\getRefundOrder::class,
|
||||
'queryAgreeStatus' => \app\cmd\QueryAgreeStatus::class,
|
||||
'queryRechargeOrder' =>\app\cmd\QueryRechargeOrder::class
|
||||
'queryRechargeOrder' =>\app\cmd\QueryRechargeOrder::class,
|
||||
'payOrderRetry' =>\app\cmd\PayOrderRetry::class,
|
||||
'agreementPaySendSms' =>\app\cmd\AgreementPaySendSms::class
|
||||
],
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue