使用自定义支付网关时排除订单计入营收的技术需求
WooCommerce Credits支付订单排除营收统计解决方案
核心问题在于:Credits支付的订单实际营收已在购买Credits时产生,需让这类订单总额为0(不计入营收),同时保留「Credits」支付方式显示。之前在process_payment阶段修改总额无效,是因为订单创建后关键数据已固化,需提前在订单生成前处理。
步骤1:购物车阶段添加全额折扣(切换支付方式时生效)
当用户选择Credits支付时,自动添加与订单总额等额的折扣,使最终结算金额为0,同时保留支付方式关联。
add_action('woocommerce_cart_calculate_fees', 'apply_credit_payment_full_discount', 10, 1); function apply_credit_payment_full_discount($cart) { if (is_admin() && !defined('DOING_AJAX')) return; // 替换为你的Credits网关ID(对应WC_Gateway_Credits类的id属性) $credit_gateway_id = 'credits'; $chosen_gateway = WC()->session->get('chosen_payment_method'); if ($chosen_gateway === $credit_gateway_id) { $total = $cart->get_total('edit'); // 添加折扣,备注为Credits支付 $cart->add_fee(__('Credits支付抵扣', 'your-text-domain'), -$total); } }
步骤2:保存原始订单金额到订单元数据
因为订单最终金额为0,需记录实际扣除的Credits金额,后续在process_payment中使用。
add_action('woocommerce_checkout_create_order', 'save_original_total_for_credit_payment', 10, 2); function save_original_total_for_credit_payment($order, $data) { $credit_gateway_id = 'credits'; $chosen_gateway = WC()->session->get('chosen_payment_method'); if ($chosen_gateway === $credit_gateway_id) { // 保存原始订单总额到自定义元字段 $order->update_meta_data('_original_order_total', $order->get_total()); // 强制设置订单总额为0(确保统计时不计入营收) $order->set_total(0.00); } }
步骤3:修改process_payment方法
调整Credits网关的支付处理逻辑,使用原始订单金额扣除用户Credits,同时确保支付方式正确显示。
class WC_Gateway_Credits extends WC_Payment_Gateway { // ... 其他已有代码 ... public function process_payment( $order_id ) { $order = wc_get_order( $order_id ); // 获取保存的原始订单金额(而非当前0总额) $original_total = $order->get_meta('_original_order_total'); // 兜底:如果元数据不存在,用订单原始总额 if (empty($original_total)) { $original_total = $order->get_total(); } // 扣除用户Credits $user_id = $order->get_user_id(); Subscriber::get_instance($user_id)->credits_used($order_id, $original_total); // 确保支付方式正确关联并保存 $order->set_payment_method($this); $order->save(); $order->payment_complete(); // 清空购物车 WC()->cart->empty_cart(); // 返回感谢页跳转 return array( 'result' => 'success', 'redirect' => $this->get_return_url( $order ) ); } }
步骤4:订单详情页补充显示原始金额
让用户在订单详情页看到实际扣除的Credits金额,避免混淆。
add_action('woocommerce_order_details_after_order_table', 'display_credit_payment_info', 10, 1); function display_credit_payment_info($order) { if ($order->get_payment_method() === 'credits') { $original_total = $order->get_meta('_original_order_total'); if ($original_total) { echo '<div class="credit-payment-info">'; echo '<p><strong>原始订单金额:</strong>' . wc_price($original_total) . '</p>'; echo '<p><strong>Credits支付金额:</strong>' . wc_price($original_total) . '</p>'; echo '</div>'; } } }
步骤5:结账页切换支付方式实时更新金额
添加JS代码,确保用户切换支付方式时,购物车金额自动刷新。
add_action('wp_footer', 'refresh_cart_on_gateway_switch'); function refresh_cart_on_gateway_switch() { if (is_checkout() && !is_wc_endpoint_url()) : ?> <script> jQuery(document).ready(function($){ $('form.checkout').on('change', 'input[name="payment_method"]', function() { $('body').trigger('update_checkout'); }); }); </script> <?php endif; }
关键说明
- 为什么之前修改
process_payment无效:订单创建后,WooCommerce已锁定支付方式与金额的关联,此时修改总额会触发内部校验,导致支付方式丢失。提前在订单生成前调整金额,能同时保留支付方式关联。 - 营收统计排除:订单总额为0时,WooCommerce不会将其计入营收报表,符合需求。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

