首页 文章

WooCommerce REST API v2:如何处理付款?

提问于
浏览
6

使用WooCommerce REST API v2,我成功地在待处理的未付款状态下创建订单 .

我可以看到我可以将 order.payment_details.paid 字段设置为 true ,这将在已完成状态下创建订单并发送已完成的订单电子邮件,但它实际上并不处理付款 .

使用REST API v2创建订单并让WooCommerce使用支付网关处理付款的正确方法是什么?

或者我是否需要在服务器端向API添加插件挂钩? (我认同)

这是我尝试过的

curl -X POST https://example.com/wc-api/v2/orders \
    -u consumer_key:consumer_secret \
    -H "Content-Type: application/json" \
    -d '{
          "order": {
            "customer_id": 2,
            "payment_details": {
              "method_id": "da_big_bank",
              "method_title": "StackOverflow Money Laundering, Inc.",
              "paid":true
            },
            "line_items": [
              {
                "product_id": 341,
                "quantity": 1
              }
            ]
          }
        }'

正如我所说,它在完成状态下生成订单,但实际上并没有用我的网关处理任何钱(这不是“StackOverflow Money Laundering,Inc . ”并且是使用我们的WooCommerce网站时可以正常工作的合法网关)

2 回答

  • 7

    由于helgatheviking同意,目前还没有办法使用WooCommerce REST API处理订单付款 .

    我最终在 woocommerce_api_create_order 过滤器中写了一个钩子,它在创建订单时立即处理付款订单 . 如果处理失败,则将错误添加到 order->post->post_excerpt 字段,使其在JSON响应中显示为 order->note .

    为此,我还必须扩展支付网关,以便其 process_payment() 方法接受 $user_id 作为输入 . 这是因为它是开箱即用的,可以对当前登录的用户进行操作,在我的情况下,在大多数情况下,可能是REST客户端登录的系统用户,而不是实际用户进行购买 .

    扩展网关的另一个好处是,现在可以返回错误而不是写入 wc_add_notice() . 由于这是一个REST服务,所以没有看到 wc_add_notice() 的输出

    add_filter('woocommerce_api_create_order', 'acme_on_api_create_order', 10, 3);
    
    /**
     * When order is created in REST client, actually make them pay for it
     * @param int $id order id
     * @param array $data order data posted by client
     * @param WC_API_Orders $api not used
     * @return array the data passed back unaltered
     */
    function acme_on_api_create_order($id, $data, $api) {
        if($data['payment_details']['method_id'] == 'acme_rest_gateway') {
            $order = wc_get_order($id);
            $order->calculate_totals();
            $acme_gateway = new WC_Acme_Gateway_For_Rest();
            $payment = $acme_gateway->process_payment($id, $data['customer_id']);
            if($payment["result"] == "success") {
                $order->update_status('completed');
            }
            else {
                $order->update_status("cancelled");
                wp_update_post(array(
                    'ID' => $id,
                    'post_excerpt' => json_encode($payment)
                ));
            }
        }
        return $data;
    }
    
    // Register the payment gateway
    add_filter('woocommerce_payment_gateways', 'acme_add_payment_gateway_class');
    
    function acme_add_payment_gateway_class($methods) {
        $methods[] = 'WC_Acme_Gateway_For_Rest';
        return $methods;
    }
    
    // Load the new payment gateway needed by REST client
    add_action('after_setup_theme', 'acme_init_rest_gateway_class');
    
    function acme_init_rest_gateway_class() {
    
        /**
         * Extend the payment gateway to work in the REST API context
         */
        class WC_Acme_Gateway_For_Rest extends WC_Acme_Gateway {
    
            /**
             * Constructor for the gateway.
             */
            public function __construct() {
                parent::__construct();
                $this->id = 'acme_rest_gateway';
            }
    
            /**
             * Process Payment. This is the same as the parent::process_payment($order_id) except that we're also passing
             * the user id rather than reading get_current_user_id().
             * And we're returning errors rather than writing them as notices
             * @param int $order_id the order id
             * @param int $user_id user id
             * @return array|null an array if success. otherwise returns nothing
             */
            function process_payment($order_id, $user_id) {
                    $order = wc_get_order( $order_id );
                /* 
                 * todo: code sending da moneez to da bank
                 */
                    return array(
                        'result'   => 'success',
                        'redirect' => $this->get_return_url( $order )
                    );
            }
        }
    }
    
  • 3

    谢谢你给我的方向 .

    我做了一些改动和简化的步骤 .

    如下:

    add_filter('woocommerce_api_order_response', 'intercept_api_response', 1, 4);
    /**
    * Here, intercept api's response to include the url of payment
    **/
    function intercept_api_response($order_data, $order)
    {
        $order_data['payment_url'] = $order->payment_url;
    
        return $order_data;
    }
    
    add_filter('woocommerce_api_create_order', 'intercept_on_api_create_order', 10, 3);
    
    
    function intercept_on_api_create_order($id, $data, $api)
    {
        if (in_array($data['payment_details']['method_id'], ['pagseguro', 'paypal'])) {
            $order = wc_get_order($id);
            $order->calculate_totals();
    
            if ($data['payment_details']['method_id'] == 'paypal') {
                $paypal = new WC_Gateway_Paypal();
                $payment = $paypal->process_payment($id);
            }
            update_post_meta($id, '_payment_url', $payment['redirect']);
        }
        return $payment;
    }
    

    我希望这可以帮助别人 . 经过大量的反复试验,这是一项艰苦的工作 .

相关问题