PayTimeout.php 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <?php
  2. /**
  3. * 订单超时自动取消定时任务
  4. */
  5. namespace app\crontab;
  6. use think\console\Command;
  7. use think\console\Input;
  8. use think\console\Output;
  9. use think\Db;
  10. use app\common\model\MemberCoinInfo;
  11. class PayTimeout extends Command
  12. {
  13. protected function configure()
  14. {
  15. $this->setName('PayTimeout')->setDescription('清理超时未支付订单');
  16. }
  17. protected function execute(Input $input, Output $output)
  18. {
  19. // 设置内存限制以防超大批次导致内存溢出
  20. ini_set('memory_limit', '1024M');
  21. $output->writeln(date('Y-m-d H:i:s') . " PayTimeout start\r\n");
  22. $this->handleTimeoutOrders($output);
  23. $output->writeln(date('Y-m-d H:i:s') . " PayTimeout end\r\n");
  24. }
  25. /**
  26. * 分批处理超时未支付的订单
  27. * @param Output $output
  28. */
  29. private function handleTimeoutOrders(Output $output)
  30. {
  31. $now = time();
  32. $limit = 500; // 单次查询和更新批次量
  33. $output->writeln("当前核对时间戳: {$now} = " . date('Y-m-d H:i:s'));
  34. while (true) {
  35. // 查询超时且需要处理的订单
  36. $list = Db::table('cy_paycpinfo')->alias('cpi')
  37. ->join('cy_pay cp', 'cpi.orderid = cp.orderid')
  38. ->where('cpi.pay_timeout', '>', 0)
  39. ->where('cpi.pay_timeout', '<', $now)
  40. ->where('cpi.payflag', 0)
  41. ->field("cpi.orderid, cp.userid")
  42. ->limit($limit)
  43. ->select();
  44. if (empty($list)) {
  45. $output->writeln("所有待处理超时订单清理完成。");
  46. break;
  47. }
  48. $count = count($list);
  49. $output->writeln("本批次发现 {$count} 条超时订单,准备执行取消...");
  50. // 取消订单:遍历每个订单,调用 releaseCoin 方法
  51. $successCount = 0;
  52. $failCount = 0;
  53. foreach ($list as $item) {
  54. $userid = $item['userid'];
  55. $orderid = $item['orderid'];
  56. $result = (new MemberCoinInfo())->releaseCoin($userid, $orderid, 3);
  57. if ($result) {
  58. $successCount++;
  59. $output->writeln("✔ 订单 {$orderid} 取消成功,用户ID: {$userid}");
  60. } else {
  61. $failCount++;
  62. $output->writeln("❌ 订单 {$orderid} 取消失败,用户ID: {$userid}");
  63. }
  64. }
  65. $output->writeln("本批次处理完成:成功 {$successCount} 条,失败 {$failCount} 条\r\n");
  66. // 若本次提取的数据不足限额,说明全部处理完毕,跳出循环
  67. if ($count < $limit) {
  68. break;
  69. }
  70. }
  71. }
  72. }