如何通过自定义WP-JSON接口处理WooCommerce未付款订单支付?
实现自定义WP-JSON接口调用支付网关完成订单支付
一、注册自定义REST路由
在主题functions.php或自定义插件中添加代码,注册符合要求的API路由:
add_action('rest_api_init', function() { register_rest_route( 'myapp', '/order-payment/(?P<order_id>\d+)/(?P<gateway_id>[a-zA-Z0-9_-]+)', [ 'methods' => WP_REST_Server::CREATABLE, // 对应POST请求 'callback' => 'myapp_process_order_payment', 'permission_callback' => 'myapp_validate_payment_permission', 'args' => [ 'order_id' => [ 'validate_callback' => function($param) { return is_numeric($param) && wc_get_order((int)$param); } ], 'gateway_id' => [ 'validate_callback' => function($param) { $gateways = WC()->payment_gateways->get_available_payment_gateways(); return isset($gateways[$param]); } ] ] ] ); });
二、权限验证函数
确保只有订单所属用户或管理员能调用接口:
function myapp_validate_payment_permission($request) { $order_id = (int)$request['order_id']; $order = wc_get_order($order_id); if (!$order) return false; $current_user_id = get_current_user_id(); // 允许订单所有者或管理员操作 return $current_user_id === $order->get_user_id() || current_user_can('manage_woocommerce'); }
三、核心支付处理函数
根据订单ID和网关ID,调用对应支付网关逻辑处理支付:
function myapp_process_order_payment($request) { $order_id = (int)$request['order_id']; $gateway_id = sanitize_text_field($request['gateway_id']); $order = wc_get_order($order_id); $gateways = WC()->payment_gateways->get_available_payment_gateways(); $gateway = $gateways[$gateway_id]; // 基础校验 if (!$order->has_status('pending')) { return new WP_REST_Response(['error' => '订单状态不是未付款,无法发起支付'], 400); } if (!$gateway->is_available()) { return new WP_REST_Response(['error' => '该支付网关未激活或不可用'], 400); } // 按不同网关处理支付 switch ($gateway_id) { case 'stripe': // Stripe网关处理:创建支付意向,返回客户端密钥 try { $stripe = $gateway->get_stripe(); $payment_intent = $stripe->paymentIntents->create([ 'amount' => $order->get_total() * 100, // Stripe以分为单位 'currency' => strtolower(get_woocommerce_currency()), 'metadata' => ['order_id' => $order_id], ]); $order->update_meta_data('_stripe_payment_intent', $payment_intent->id); $order->save(); return new WP_REST_Response([ 'success' => true, 'payment_intent_id' => $payment_intent->id, 'client_secret' => $payment_intent->client_secret, 'order_id' => $order_id ], 200); } catch (Exception $e) { return new WP_REST_Response(['error' => $e->getMessage()], 500); } break; case 'paypal': // PayPal网关处理:创建订单,返回授权链接 try { $paypal_order = $gateway->create_order($order); $approval_url = ''; foreach ($paypal_order->links as $link) { if ($link->rel === 'approve') { $approval_url = $link->href; break; } } $order->update_meta_data('_paypal_order_id', $paypal_order->id); $order->save(); return new WP_REST_Response([ 'success' => true, 'paypal_order_id' => $paypal_order->id, 'approval_url' => $approval_url, 'order_id' => $order_id ], 200); } catch (Exception $e) { return new WP_REST_Response(['error' => $e->getMessage()], 500); } break; default: // 自定义网关处理:调用网关自带的支付处理方法 $payment_result = $gateway->process_payment($order_id); if ($payment_result['result'] === 'success') { return new WP_REST_Response([ 'success' => true, 'redirect' => $payment_result['redirect'], 'order_id' => $order_id ], 200); } else { return new WP_REST_Response(['error' => $payment_result['message']], 400); } break; } }
四、前端调用示例
通过POST请求调用接口,需携带WordPress的CSRF验证nonce:
fetch('https://example.com/wp-json/myapp/order-payment/123/stripe', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': wpApiSettings.nonce // 需确保前端已加载wpApiSettings对象 } }) .then(response => response.json()) .then(data => { if (data.success) { // 示例:Stripe前端支付流程 Stripe('你的Stripe公钥').confirmCardPayment(data.client_secret, { payment_method: { card: cardElement, billing_details: { name: '用户姓名' } } }).then(result => { if (result.error) { console.error('支付失败:', result.error.message); } else { window.location.href = '/order-received/' + data.order_id; } }); } else { console.error('请求失败:', data.error); } });
关键注意事项
- 确保WooCommerce已激活,目标支付网关已配置并启用。
- Stripe/PayPal的处理逻辑需对应其官方WooCommerce插件版本调整,避免API变动导致错误。
- 必须传递
X-WP-Nonce头进行CSRF验证,防止恶意请求。 - 支付完成后,依赖网关的webhook自动更新订单状态(如Stripe webhook会将订单标记为已完成)。
内容的提问来源于stack exchange,提问作者Sarwar Hasan
相关产品推荐
相关产品推荐

