如何在Laravel中对比Firestore日期与当前日期
问题:Firestore日期对比导致Cron定时扣费任务失效
我是Laravel和Firebase新手,需要对比Firestore中存储的日期(格式为"2023-08-31")和当前日期,判断插入日期是否大于等于当前日期。我设置了Cron定时任务,预期当前日期大于插入日期时执行用户扣费,但Cron运行正常,却因为日期判断逻辑问题无法完成扣费。
以下是我的代码:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Carbon\Carbon; use DateTime; use Illuminate\Support\Facades\Route; use App\Http\Middleware\VerifyCsrfToken; use Illuminate\Http\Request; class DailyChargez extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'DailyChargeUserz:cron'; /** * The console command description. * * @var string */ protected $description = 'Command description'; /** * Execute the console command. * * @return int */ public function handle() { \Log::info("Cron is working fine daily!"); $mydate = Carbon::now(); $daily = app('firebase.firestore')->database()->collection('Payment'); $query1 = $daily->where('paymentType', '==', 'Recurring Payment') ->where('active', '=', true) ->where('frequence', '==', 'Daily') ->where('deductionDate', '<=', $mydate); $documents = $query1->documents(); foreach ($documents as $document) { if ($document->exists()) { $postDataz = [ 'authorization_code' => $document->data()['authenticate'], 'email' => $document->data()['email'], 'amount' => $document->data()['amountToCharge'] * 100, "metadata" => [ "custom_fields" => [ [ "value" => $document->data()['paymentMethod'], "display_name" => "Payment Method", "variable_name" => "payment method", ], [ "value" => $document->data()['packageName'], "display_name" => "Package Name", "variable_name" => "package name", ], ] ] ]; } $url = "https://api.paystack.co/transaction/charge_authorization"; $fields_stringz = http_build_query($postDataz); //open connection $ch = curl_init(); //set the url, number of POST vars, POST data curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_POST, true); curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_stringz); curl_setopt($ch, CURLOPT_HTTPHEADER, array( "Authorization: Bearer *******", "Cache-Control: no-cache", )); //So that curl_exec returns the contents of the cURL; rather than echoing it curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); $info = json_decode($result); } } }
解决方案
问题根源是日期类型不匹配:Firestore中存储的是YYYY-MM-DD格式的字符串日期,但你传入查询的Carbon::now()是带时分秒的Carbon对象,Firestore无法正确对比字符串和DateTime类型的值,导致查询无结果,自然不会执行扣费。
核心修正步骤:
- 统一日期格式为字符串:将当前日期转换为和Firestore一致的
Y-m-d格式$mydate = Carbon::now()->format('Y-m-d'); - 修正请求逻辑位置:把curl请求(或HTTP客户端请求)放到
if ($document->exists())代码块内部,避免$postDataz未定义时触发请求报错 - 清理冗余依赖:移除代码中无用的引入(
Route、VerifyCsrfToken、Request、DateTime),精简代码
优化后的完整代码:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Carbon\Carbon; use Illuminate\Support\Facades\Http; class DailyChargez extends Command { protected $signature = 'DailyChargeUserz:cron'; protected $description = 'Daily recurring payment charge'; public function handle() { \Log::info("Daily charge cron executed"); // 转换为Firestore存储的日期字符串格式 $currentDate = Carbon::now()->format('Y-m-d'); $paymentCollection = app('firebase.firestore')->database()->collection('Payment'); $query = $paymentCollection->where('paymentType', '==', 'Recurring Payment') ->where('active', '=', true) ->where('frequence', '==', 'Daily') ->where('deductionDate', '<=', $currentDate); foreach ($query->documents() as $document) { if (!$document->exists()) continue; $data = $document->data(); $postData = [ 'authorization_code' => $data['authenticate'], 'email' => $data['email'], 'amount' => $data['amountToCharge'] * 100, "metadata" => [ "custom_fields" => [ [ "value" => $data['paymentMethod'], "display_name" => "Payment Method", "variable_name" => "payment_method", ], [ "value" => $data['packageName'], "display_name" => "Package Name", "variable_name" => "package_name", ], ] ] ]; // 使用Laravel HTTP客户端替代原生curl,代码更简洁 $response = Http::withHeaders([ "Authorization" => "Bearer *******", "Cache-Control" => "no-cache", ])->post("https://api.paystack.co/transaction/charge_authorization", $postData); $result = $response->json(); // 记录扣费结果日志,方便排查问题 \Log::info("Charge attempt for {$data['email']}", [ 'document_id' => $document->id(), 'result' => $result ]); } return Command::SUCCESS; } }
额外建议:
- 可以考虑将Firestore中的日期字段改为Timestamp类型,这样日期对比会更精准,也支持带时间的判断
- 添加异常处理,避免单个请求失败导致整个Cron任务中断
- 定期清理失效的
active=false的支付记录,优化查询性能
内容的提问来源于stack exchange,提问作者Pamy Pamly
相关产品推荐
相关产品推荐

