我如何与向我发送POST请求以响应我发送的订单信息的第三方服务交互?

时间:2016-05-02 作者:Nozulani

我正在为Wordpress开发一个支付网关。我应该将数据发送给第三方,并从他们那里获得确认码(和其他信息)。问题是他们没有将此确认码作为对我的POST请求的直接响应返回。相反,他们会处理它,并将POST请求发送到我可以指定的URL。因此,我无法使用wp\\u remote\\u post。

我如何实现这一点,如果可能的话,确保用户留在我的页面上?

谢谢

编辑:他们想让我用代码编辑这个,所以它是:

<?php
class SPYR_AuthorizeNet_AIM extends WC_Payment_Gateway {

// Setup our Gateway\'s id, description and other values
function __construct() {

    // The global ID for this Payment method
    $this->id = "spyr_authorizenet_aim";

    // The Title shown on the top of the Payment Gateways Page next to all the other Payment Gateways
    $this->method_title = __( "Authorize.net AIM", \'spyr-authorizenet-aim\' );

    // The description for this Payment Gateway, shown on the actual Payment options page on the backend
    $this->method_description = __( "Authorize.net AIM Payment Gateway Plug-in for WooCommerce", \'spyr-authorizenet-aim\' );

    // The title to be used for the vertical tabs that can be ordered top to bottom
    $this->title = __( "Authorize.net AIM", \'spyr-authorizenet-aim\' );

    // If you want to show an image next to the gateway\'s name on the frontend, enter a URL to an image.
    $this->icon = null;

    // Bool. Can be set to true if you want payment fields to show on the checkout 
    // if doing a direct integration, which we are doing in this case
    $this->has_fields = true;

    // Supports the default credit card form
    $this->supports = array( \'default_credit_card_form\' );

    // This basically defines your settings which are then loaded with init_settings()
    $this->init_form_fields();

    // After init_settings() is called, you can get the settings and load them into variables, e.g:
    // $this->title = $this->get_option( \'title\' );
    $this->init_settings();

    // Turn these settings into variables we can use
    foreach ( $this->settings as $setting_key => $value ) {
        $this->$setting_key = $value;
    }

    // Lets check for SSL
    add_action( \'admin_notices\', array( $this,  \'do_ssl_check\' ) );

    // Save settings
    if ( is_admin() ) {
        // Versions over 2.0
        // Save our administration options. Since we are not going to be doing anything special
        // we have not defined \'process_admin_options\' in this class so the method in the parent
        // class will be used instead
        add_action( \'woocommerce_update_options_payment_gateways_\' . $this->id, array( $this, \'process_admin_options\' ) );
    }       
} // End __construct()

// Build the administration fields for this specific Gateway
public function init_form_fields() {
    $this->form_fields = array(
        \'enabled\' => array(
            \'title\'     => __( \'Enable / Disable\', \'spyr-authorizenet-aim\' ),
            \'label\'     => __( \'Enable this payment gateway\', \'spyr-authorizenet-aim\' ),
            \'type\'      => \'checkbox\',
            \'default\'   => \'no\',
        ),
        \'title\' => array(
            \'title\'     => __( \'Title\', \'spyr-authorizenet-aim\' ),
            \'type\'      => \'text\',
            \'desc_tip\'  => __( \'Payment title the customer will see during the checkout process.\', \'spyr-authorizenet-aim\' ),
            \'default\'   => __( \'Credit card\', \'spyr-authorizenet-aim\' ),
        ),
        \'description\' => array(
            \'title\'     => __( \'Description\', \'spyr-authorizenet-aim\' ),
            \'type\'      => \'textarea\',
            \'desc_tip\'  => __( \'Payment description the customer will see during the checkout process.\', \'spyr-authorizenet-aim\' ),
            \'default\'   => __( \'Pay securely using your credit card.\', \'spyr-authorizenet-aim\' ),
            \'css\'       => \'max-width:350px;\'
        ),
        \'api_login\' => array(
            \'title\'     => __( \'Authorize.net API Login\', \'spyr-authorizenet-aim\' ),
            \'type\'      => \'text\',
            \'desc_tip\'  => __( \'This is the API Login provided by Authorize.net when you signed up for an account.\', \'spyr-authorizenet-aim\' ),
        ),
        \'trans_key\' => array(
            \'title\'     => __( \'Authorize.net Transaction Key\', \'spyr-authorizenet-aim\' ),
            \'type\'      => \'password\',
            \'desc_tip\'  => __( \'This is the Transaction Key provided by Authorize.net when you signed up for an account.\', \'spyr-authorizenet-aim\' ),
        ),
        \'environment\' => array(
            \'title\'     => __( \'Authorize.net Test Mode\', \'spyr-authorizenet-aim\' ),
            \'label\'     => __( \'Enable Test Mode\', \'spyr-authorizenet-aim\' ),
            \'type\'      => \'checkbox\',
            \'description\' => __( \'Place the payment gateway in test mode.\', \'spyr-authorizenet-aim\' ),
            \'default\'   => \'no\',
        )
    );      
}

// Submit payment and handle response
public function process_payment( $order_id ) {
    global $woocommerce;

    // Get this Order\'s information so that we know
    // who to charge and how much
    $customer_order = new WC_Order( $order_id );

    // Are we testing right now or is it a real transaction
    $environment = ( $this->environment == "yes" ) ? \'TRUE\' : \'FALSE\';

    // Decide which URL to post to
    $environment_url = ( "FALSE" == $environment ) 
                       ? \'https://secure.authorize.net/gateway/transact.dll\'
                       : \'https://test.authorize.net/gateway/transact.dll\';

    // This is where the fun stuff begins
    $payload = array(
        // Authorize.net Credentials and API Info
        "x_tran_key"            => $this->trans_key,
        "x_login"               => $this->api_login,
        "x_version"             => "3.1",

        // Order total
        "x_amount"              => $customer_order->order_total,

        // Credit Card Information
        "x_card_num"            => str_replace( array(\' \', \'-\' ), \'\', $_POST[\'spyr_authorizenet_aim-card-number\'] ),
        "x_card_code"           => ( isset( $_POST[\'spyr_authorizenet_aim-card-cvc\'] ) ) ? $_POST[\'spyr_authorizenet_aim-card-cvc\'] : \'\',
        "x_exp_date"            => str_replace( array( \'/\', \' \'), \'\', $_POST[\'spyr_authorizenet_aim-card-expiry\'] ),

        "x_type"                => \'AUTH_CAPTURE\',
        "x_invoice_num"         => str_replace( "#", "", $customer_order->get_order_number() ),
        "x_test_request"        => $environment,
        "x_delim_char"          => \'|\',
        "x_encap_char"          => \'\',
        "x_delim_data"          => "TRUE",
        "x_relay_response"      => "FALSE",
        "x_method"              => "CC",

        // Billing Information
        "x_first_name"          => $customer_order->billing_first_name,
        "x_last_name"           => $customer_order->billing_last_name,
        "x_address"             => $customer_order->billing_address_1,
        "x_city"                => $customer_order->billing_city,
        "x_state"               => $customer_order->billing_state,
        "x_zip"                 => $customer_order->billing_postcode,
        "x_country"             => $customer_order->billing_country,
        "x_phone"               => $customer_order->billing_phone,
        "x_email"               => $customer_order->billing_email,

        // Shipping Information
        "x_ship_to_first_name"  => $customer_order->shipping_first_name,
        "x_ship_to_last_name"   => $customer_order->shipping_last_name,
        "x_ship_to_company"     => $customer_order->shipping_company,
        "x_ship_to_address"     => $customer_order->shipping_address_1,
        "x_ship_to_city"        => $customer_order->shipping_city,
        "x_ship_to_country"     => $customer_order->shipping_country,
        "x_ship_to_state"       => $customer_order->shipping_state,
        "x_ship_to_zip"         => $customer_order->shipping_postcode,

        // Some Customer Information
        "x_cust_id"             => $customer_order->user_id,
        "x_customer_ip"         => $_SERVER[\'REMOTE_ADDR\'],

    );

    // Send this payload to Authorize.net for processing
    $response = wp_remote_post( $environment_url, array(
        \'method\'    => \'POST\',
        \'body\'      => http_build_query( $payload ),
        \'timeout\'   => 90,
        \'sslverify\' => false,
    ) );

    if ( is_wp_error( $response ) ) 
        throw new Exception( __( \'We are currently experiencing problems trying to connect to this payment gateway. Sorry for the inconvenience.\', \'spyr-authorizenet-aim\' ) );

    if ( empty( $response[\'body\'] ) )
        throw new Exception( __( \'Authorize.net\\\'s Response was empty.\', \'spyr-authorizenet-aim\' ) );

    // Retrieve the body\'s resopnse if no errors found
    $response_body = wp_remote_retrieve_body( $response );

    // Parse the response into something we can read
    foreach ( preg_split( "/\\r?\\n/", $response_body ) as $line ) {
        $resp = explode( "|", $line );
    }

    // Get the values we need
    $r[\'response_code\']             = $resp[0];
    $r[\'response_sub_code\']         = $resp[1];
    $r[\'response_reason_code\']      = $resp[2];
    $r[\'response_reason_text\']      = $resp[3];

    // Test the code to know if the transaction went through or not.
    // 1 or 4 means the transaction was a success
    if ( ( $r[\'response_code\'] == 1 ) || ( $r[\'response_code\'] == 4 ) ) {
        // Payment has been successful
        $customer_order->add_order_note( __( \'Authorize.net payment completed.\', \'spyr-authorizenet-aim\' ) );

        // Mark order as Paid
        $customer_order->payment_complete();

        // Empty the cart (Very important step)
        $woocommerce->cart->empty_cart();

        // Redirect to thank you page
        return array(
            \'result\'   => \'success\',
            \'redirect\' => $this->get_return_url( $customer_order ),
        );
    } else {
        // Transaction was not succesful
        // Add notice to the cart
        wc_add_notice( $r[\'response_reason_text\'], \'error\' );
        // Add note to the order for your reference
        $customer_order->add_order_note( \'Error: \'. $r[\'response_reason_text\'] );
    }

}

// Validate fields
public function validate_fields() {
    return true;
}

// Check if we are forcing SSL on checkout pages
// Custom function not required by the Gateway
public function do_ssl_check() {
    if( $this->enabled == "yes" ) {
        if( get_option( \'woocommerce_force_ssl_checkout\' ) == "no" ) {
            echo "<div class=\\"error\\"><p>". sprintf( __( "<strong>%s</strong> is enabled and WooCommerce is not forcing the SSL certificate on your checkout page. Please ensure that you have a valid SSL certificate and that you are <a href=\\"%s\\">forcing the checkout pages to be secured.</a>" ), $this->method_title, admin_url( \'admin.php?page=wc-settings&tab=checkout\' ) ) ."</p></div>";  
        }
    }       
}}

1 个回复
最合适的回答,由SO网友:TheDeadMedic 整理而成

因为我怀疑“漂亮的”URL在这里很重要,所以使用AJAX api创建端点/处理程序非常容易(另一种选择是使用重写api并监听结果)。

不要被术语“AJAX”所拖延——这只是WordPress安装中的一个脚本,它将为作为action 参数(通过GET或POST)。

例如example.com/wp-admin/admin-ajax.php?action=gateway:

function wpse_225366_gateway_response() {
    // Do your thang

    exit;
}

// The wp_ajax_nopriv_{action} hook fires for non-authenticated users
add_action( \'wp_ajax_nopriv_gateway\', \'wpse_225366_gateway_response\' );

// The wp_ajax_{action} hook fires for authenticated users
add_action( \'wp_ajax_gateway\',        \'wpse_225366_gateway_response\' );
您可能希望将该操作称为比gateway, 但我希望这能说明事情是如何运作的。

您可以使用以下内容以编程方式获取响应URL:

$response_url = admin_url( \'admin-ajax.php?action=gateway\' );

相关推荐