如何让WooCommerce为Simple类型产品生成并保存stripe_payment_token?
解决WooCommerce Simple产品试用场景下Stripe支付令牌缺失问题
核心原因
WooCommerce Subscriptions插件会自动处理订阅产品的支付令牌生成与存储逻辑,但Simple类型产品默认没有这套机制,因此需要手动实现支付令牌的捕获与保存。
解决方案步骤
1. 强制零金额订单生成Stripe支付令牌
默认情况下Stripe网关会跳过零金额订单的支付令牌生成,需要通过钩子强制启用该逻辑:
add_filter('wc_stripe_zero_amount_requires_payment_method', '__return_true');
2. 捕获并保存支付令牌到订单元数据
在订单创建时,从结账请求中提取Stripe令牌,将其保存到对应订单的元数据中:
function save_stripe_payment_token_to_order($order) { // 仅处理带试用天数的Simple产品订单 $has_trial = false; foreach ($order->get_items() as $item) { $product = $item->get_product(); if ($product->is_type('simple') && get_post_meta($product->get_id(), PRODUCUT_TRIAL_PERIOD, true)) { $has_trial = true; break; } } if (!$has_trial) return; // 获取并保存Stripe令牌 $stripe_token = isset($_POST['stripe_token']) ? sanitize_text_field($_POST['stripe_token']) : ''; if ($stripe_token) { $order->update_meta_data('stripe_payment_token', $stripe_token); $order->save(); } } add_action('woocommerce_checkout_create_order', 'save_stripe_payment_token_to_order');
3. 试用到期后触发令牌扣费逻辑
通过定时任务定期检查到期的试用订单,调用Stripe API使用保存的令牌完成扣费:
function process_trial_charge($order_id) { $order = wc_get_order($order_id); if (!$order) return; // 校验订单是否符合扣费条件 $stripe_token = $order->get_meta('stripe_payment_token'); $trial_days = 0; foreach ($order->get_items() as $item) { $product = $item->get_product(); $trial_days = get_post_meta($product->get_id(), PRODUCUT_TRIAL_PERIOD, true); if ($trial_days) break; } if (!$stripe_token || $order->is_paid() || $trial_days <= 0) return; // 检查试用是否到期 $order_date = $order->get_date_created(); $trial_end_date = $order_date->modify("+$trial_days days"); if (current_time('timestamp') < $trial_end_date->getTimestamp()) return; // 调用Stripe API执行扣费 try { \Stripe\Stripe::setApiKey(WC_Stripe_Helper::get_secret_key()); $charge = \Stripe\Charge::create([ 'amount' => $order->get_total() * 100, // Stripe以分为单位计费 'currency' => $order->get_currency(), 'source' => $stripe_token, 'description' => '试用到期扣费 - 订单#' . $order_id, 'metadata' => ['order_id' => $order_id] ]); // 扣费成功后更新订单状态 if ($charge->status === 'succeeded') { $order->payment_complete($charge->id); $order->add_order_note('试用到期,已通过Stripe完成扣费,Charge ID: ' . $charge->id); } } catch (\Stripe\Exception\CardException $e) { $order->add_order_note('试用扣费失败:' . $e->getError()->message); } catch (\Exception $e) { $order->add_order_note('试用扣费异常:' . $e->getMessage()); } }
4. 配置定时任务触发扣费
添加WordPress定时任务,每天执行一次到期订单检查:
function setup_trial_charge_cron() { if (!wp_next_scheduled('daily_trial_charge_process')) { wp_schedule_event(time(), 'daily', 'daily_trial_charge_process'); } } add_action('wp', 'setup_trial_charge_cron'); // 遍历所有符合条件的订单执行扣费 function run_daily_trial_charges() { $orders = wc_get_orders([ 'status' => 'on-hold', // 假设试用订单状态为on-hold 'type' => 'simple', 'meta_key' => 'stripe_payment_token', 'meta_compare' => 'EXISTS' ]); foreach ($orders as $order) { process_trial_charge($order->get_id()); } } add_action('daily_trial_charge_process', 'run_daily_trial_charges');
注意事项
- 确保Stripe插件版本为最新,API密钥配置正确
- 测试阶段可缩短试用天数,快速验证流程
- 需处理卡片过期、余额不足等异常场景,保证订单状态同步更新
内容的提问来源于stack exchange,提问作者mrabro
相关产品推荐
相关产品推荐

