如何用PHP通过Stripe API获取上月含Metadata的全部支付数据?
如何用PHP通过Stripe API获取上月含Metadata的全量支付数据?
问题背景
需要用PHP通过Stripe API获取上月日历周期内的所有支付数据及关联信息(包括Metadata),尝试两种方法均存在问题:
方法一:无法获取全部支付数据
// Set your Stripe API key \Stripe\Stripe::setApiKey('sk_live_xxxxxxxxxxxxxxxxx'); $start = strtotime("first day of previous month"); $end = strtotime("last day of previous month"); $payments = \Stripe\PaymentIntent::all([ 'created' => [ 'gte' => $start, 'lte' => $end, ], 'limit' => 100, ]);
问题出在:Stripe API列表接口默认分页,limit=100仅返回第一页数据,未处理后续分页会遗漏大量数据;另外created筛选的是PaymentIntent的创建时间,而非实际支付成功时间,若存在上月创建但次月支付、或上月支付但创建时间在上上月的订单,也会被排除。
方法二:能获取全量支付数据,但无法直接获取Metadata
// Set your Stripe API key \Stripe\Stripe::setApiKey('sk_live_xxxxxxxxxxxxxxxxx'); $start = strtotime("first day of previous month"); $end = strtotime("last day of previous month"); $transactions = \Stripe\BalanceTransaction::all([ 'created' => [ 'gte' => $start, 'lte' => $end, ], 'limit' => 100, ]);
问题原因:BalanceTransaction是余额变动记录,本身不存储Metadata,Metadata实际存储在关联的PaymentIntent或Charge对象中。
解决方案
方案1:优化PaymentIntent查询,直接获取全量含Metadata的数据
解决分页问题,同时可按需筛选支付成功时间(更精准):
\Stripe\Stripe::setApiKey('sk_live_xxxxxxxxxxxxxxxxx'); // 转换上月时间范围为秒级时间戳 $start = strtotime("first day of previous month 00:00:00"); $end = strtotime("last day of previous month 23:59:59"); $allPayments = []; $lastId = null; // 循环分页拉取所有数据 do { $params = [ // 按创建时间筛选,若要按支付成功时间筛选,替换为下面的paid_at参数 'created' => [ 'gte' => $start, 'lte' => $end, ], 'limit' => 100, // 可选:仅筛选成功支付的订单 // 'status' => 'succeeded', // 可选:按支付成功时间筛选(需Stripe API版本支持) // 'paid_at' => [ // 'gte' => $start, // 'lte' => $end, // ], ]; // 设置分页起始ID(若有上一页数据) if ($lastId) { $params['starting_after'] = $lastId; } $payments = \Stripe\PaymentIntent::all($params); // 收集当前页数据,直接获取Metadata foreach ($payments->data as $payment) { $allPayments[] = $payment; // 访问Metadata示例:$payment->metadata->custom_key } // 更新最后一条ID,用于下一页查询 $lastId = end($payments->data)?->id; } while ($payments->has_more); // $allPayments即为全量包含Metadata的PaymentIntent数据
说明:
- 通过
has_more判断是否还有后续分页,循环拉取直到获取全部数据; - 若需精准统计上月实际完成的支付,建议使用
paid_at筛选并搭配status=succeeded; - Metadata直接包含在PaymentIntent对象中,可通过
$payment->metadata直接访问。
方案2:基于BalanceTransaction关联获取Metadata
通过BalanceTransaction的source字段,拉取关联的PaymentIntent或Charge对象,进而拿到Metadata:
\Stripe\Stripe::setApiKey('sk_live_xxxxxxxxxxxxxxxxx'); $start = strtotime("first day of previous month 00:00:00"); $end = strtotime("last day of previous month 23:59:59"); $allTransactionsWithMetadata = []; $lastId = null; // 分页拉取所有BalanceTransaction do { $params = [ 'created' => [ 'gte' => $start, 'lte' => $end, ], 'limit' => 100, ]; if ($lastId) { $params['starting_after'] = $lastId; } $transactions = \Stripe\BalanceTransaction::all($params); foreach ($transactions->data as $txn) { $metadata = []; // 根据关联对象类型拉取详情 if ($txn->source->object === 'payment_intent') { $paymentIntent = \Stripe\PaymentIntent::retrieve($txn->source->id); $metadata = $paymentIntent->metadata->toArray(); } elseif ($txn->source->object === 'charge') { $charge = \Stripe\Charge::retrieve($txn->source->id); $metadata = $charge->metadata->toArray(); } // 组装包含Metadata的交易数据 $allTransactionsWithMetadata[] = [ 'balance_transaction' => $txn->toArray(), 'metadata' => $metadata ]; } $lastId = end($transactions->data)?->id; } while ($transactions->has_more); // $allTransactionsWithMetadata即为带Metadata的全量交易数据
说明:
- BalanceTransaction的
source字段包含关联对象的类型(payment_intent/charge)和ID; - 注意API调用次数限制,若数据量较大,建议批量处理或提前通过Webhooks存储Metadata,避免频繁调用。
内容的提问来源于stack exchange,提问作者Sonja
相关产品推荐
相关产品推荐

