WooCommerce REST API v2: How to process payment?

As helgatheviking concurred, there currently isn't a way to process payment of an order with the WooCommerce REST API.

I ended up writing a hook into the woocommerce_api_create_order filter that immediately processes the order for payment when the order is created. If the processing fails, then the errors are added to the order->post->post_excerpt field which makes it appear as order->note in the JSON response.

For this to work, I also had to extend the payment gateway so that its process_payment() method would accept a $user_id as an input. This is because it's coded out of the box to operate on the currently logged in user, which, in my case, and probably most cases, is the system user that the REST client logs in as, not the actual user making a purchase.

The other benefit of extending the gateway turned out to be that now errors can be returned rather than written to wc_add_notice(). Since this is a REST service, nothing ever sees the output of 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 )
                );
        }
    }
}

Thank you for the direction that you gave me.

I made some changes and simplified steps.

As follows:

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;
}

I hope this may help someone else. It was hard work with lots of trial and error.