Laravel中使用Authorize.Net ARB无法获取交易ID的问题求助
嘿,我之前在Laravel里集成Authorize.Net ARB的时候也碰到过这个问题——毕竟ARB是后台自动执行的定期计费任务,创建订阅时确实拿不到每笔实际交易的transaction ID。下面是几个靠谱的解决办法,亲测有效:
方法1:用Webhook实时接收交易通知
这是最推荐的方式,Authorize.Net会在每笔定期交易成功完成时,主动给你指定的URL发送POST请求,里面就包含完整的交易详情(包括transaction ID)。
具体步骤:
- 先去Authorize.Net后台配置Webhook,设置你的Laravel站点接收通知的URL(比如
https://your-domain.com/authorize-net/webhook),并勾选net.authorize.payment.authcapture.created这类和交易成功相关的事件类型。 - 在Laravel里创建路由和控制器来处理通知:
// routes/web.php Route::post('/authorize-net/webhook', [AuthorizeNetWebhookController::class, 'handle']);
- 控制器里一定要先验证请求的合法性(防止伪造请求),再提取transaction ID:
// app/Http/Controllers/AuthorizeNetWebhookController.php use Illuminate\Http\Request; use net\authorize\api\util\SignatureValidator; class AuthorizeNetWebhookController extends Controller { public function handle(Request $request) { // 验证Authorize.Net的签名,这一步非常重要! $signatureHeader = $request->header('X-ANET-Signature'); $payload = $request->getContent(); $validator = new SignatureValidator(); $isValid = $validator->validate($payload, $signatureHeader, env('AUTHORIZE_NET_WEBHOOK_SIGNATURE_KEY')); if (!$isValid) { return response()->json(['status' => 'invalid'], 403); } // 解析请求体,获取交易ID $transactionData = json_decode($payload, true); $transactionId = $transactionData['payload']['transactionResponse']['transId']; $subscriptionId = $transactionData['payload']['subscriptionId']; // 把transaction ID和对应的用户订阅关联,保存到数据库 // 比如: // $subscription = Subscription::where('authorize_net_subscription_id', $subscriptionId)->first(); // $subscription->transactions()->create(['transaction_id' => $transactionId, ...]); return response()->json(['status' => 'success'], 200); } }
注意:Webhook的签名密钥需要在Authorize.Net后台生成,一定要妥善保管在环境变量里。
方法2:定期调用API查询交易记录
如果Webhook的实时通知不适合你的业务场景,也可以用Laravel的定时任务,定期调用Authorize.Net的交易列表API,查询指定订阅的交易记录来获取transaction ID。
示例代码:
// 可以放在自定义的Artisan命令或者任务类里 use net\authorize\api\contract\v1 as AnetAPI; use net\authorize\api\controller as AnetController; use Illuminate\Support\Facades\Log; public function handle() { // 初始化API认证 $merchantAuth = new AnetAPI\MerchantAuthenticationType(); $merchantAuth->setName(env('AUTHORIZE_NET_API_LOGIN_ID')); $merchantAuth->setTransactionKey(env('AUTHORIZE_NET_TRANSACTION_KEY')); // 构建查询请求 $request = new AnetAPI\GetTransactionListRequest(); $request->setMerchantAuthentication($merchantAuth); // 按订阅ID过滤,这里可以遍历你数据库里的所有ARB订阅ID $request->setSubscriptionId('YOUR_SUBSCRIPTION_ID'); // 查询最近24小时的交易,避免重复查询 $request->setStartDate(now()->subDay()); $request->setEndDate(now()); // 执行请求 $controller = new AnetController\GetTransactionListController($request); $response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX); // 生产环境换PRODUCTION if ($response && $response->getMessages()->getResultCode() === 'Ok') { foreach ($response->getTransactions() as $transaction) { $transactionId = $transaction->getTransId(); // 检查这个transaction ID是否已经存在于你的数据库,避免重复保存 // 然后关联到对应的订阅记录 // ... } } else { $errors = $response->getMessages()->getMessage(); foreach ($errors as $error) { Log::error("Authorize.Net交易查询失败: {$error->getText()}"); } } }
然后在app/Console/Kernel.php里配置定时任务,比如每天凌晨跑一次:
protected function schedule(Schedule $schedule) { $schedule->command('authorize-net:fetch-transactions')->dailyAt('02:00'); }
方法3:开启交易通知邮件(辅助手段)
这不算编程层面的解决方案,但你可以在Authorize.Net后台开启交易成功的邮件通知,邮件里会包含transaction ID,作为手动查询的备用方式。不过还是建议用前两种方法实现自动化获取。
最后提醒一下:创建ARB订阅时返回的subscriptionId只是订阅的唯一标识,每笔实际交易的transId只有在交易执行后才能获取,所以必须通过上述方式来获取哦。
内容的提问来源于stack exchange,提问作者Farhan Khan
相关产品推荐
相关产品推荐

