WooCommerce REST API v2: Как да обработя плащане?

Използвайки 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)


person Kirby    schedule 18.06.2015    source източник
comment
Не вярвам, че можете да обработите плащане чрез API. Най-малкото, като гледам документи за API, не виждам раздел за обработка на плащането.   -  person helgatheviking    schedule 19.06.2015


Отговори (3)


Както helgatheviking се съгласи, в момента няма начин да се обработи плащане на поръчка с WooCommerce REST API.

В крайна сметка написах кука във филтъра woocommerce_api_create_order, който незабавно обработва поръчката за плащане, когато поръчката бъде създадена. Ако обработката е неуспешна, тогава грешките се добавят към полето order->post->post_excerpt, което го кара да се показва като order->note в JSON отговора.

За да работи това, трябваше също да разширя шлюза за плащане, така че неговият 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 )
                );
        }
    }
}
person Kirby    schedule 19.06.2015

Благодаря ти за насоката, която ми даде.

Направих някои промени и опростих стъпките.

Както следва:

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

Надявам се това да помогне на някой друг. Беше тежка работа с много проби и грешки.

person Eder Ribeiro    schedule 03.11.2015
comment
Как да направите плащане с помощта на този плъгин WooCommerce PayPal, захранван от Braintree Payment Gateway чрез WooCommerce REST API - person Mr. Ajay; 25.12.2017
comment
Тази версия пропуска критичната стъпка за разширяване на шлюза и предаване на потребителско име в процеса на извикване на метода на плащане, правилно ли е? като в: функция process_payment($order_id, $user_id), Приетият отговор работи за мен. - person Claytronicon; 02.02.2018

Ако НЕ се занимавате с хоствани шлюзове за плащане (такива, които изискват потребителите да пренасочват към собствения си домейн, за да обработват плащания като paypal), тогава можете просто да го направите, както го прави WC, чрез ajax заявка:

// this is a function as a callback for a restful api - process_payment

// collect payment related info: billing, shipping info, including shipping_method & payment_method

// put all that info inside $_POST global var

// so that the nonce won't fail
$_REQUEST['_wpnonce'] =
        wp_create_nonce( 'woocommerce-process_checkout' );

// make it look like an ajax request
wc_maybe_define_constant('DOING_AJAX', 1);

add_filter('woocommerce_payment_successful_result', function($response) {
     // wp_send_json appropriate response
}

WC()->checkout()->process_checkout();

WC()->checkout()->process_checkout() ще създаде поръчка за вас, като посочи, че WC()->cart не е празно.

Можете също да опитате това за хоствани шлюзове за плащане, но то ще върне redirect, което можете да отворите в уеб изглед на мобилно приложение и да вземете плащане.

https://gist.github.com/swport/afd9292412752df9e2e086ac38030e8f

person Sumit Wadhwa    schedule 23.06.2020