Skip to content
Advertisement

Custom action button in WooCommerce admin orders with an external api call

I have created a function to add a custom action button on the admin order list, this is to cross-check the actual payment status with payment gateway.

add_filter( 'woocommerce_admin_order_actions', 'add_custom_order_status_actions_button', 100, 2 );
function add_custom_order_status_actions_button( $actions, $order ) {

    if ( $order->has_status( array( 'pending' ) ) ) {
        //if ( $order->has_status( array( 'on-hold' ) ) ) {

         $my_site_options = get_option('pay_settings');


            $mpay_adr = "https://www.apiurl.com";
            $hashKey=$my_site_options['secret'];
            $merchantid=$my_site_options['merchant_id'];


          $sHash = strtoupper(hash('sha256', $hashKey."Continue".str_pad($merchantid, 10, '0', STR_PAD_LEFT).str_pad($order->get_id(), 20, '0', STR_PAD_LEFT).str_pad(($order->get_total()*100), 12, '0', STR_PAD_LEFT)));

          $mpay_args = array(

                'secureHash'        => $sHash,

                'mid'               => str_pad($merchantid, 10, '0', STR_PAD_LEFT),

                'invno'             => str_pad($order->get_id(), 20, '0', STR_PAD_LEFT),

                'amt'               => str_pad(($order->get_total()*100), 12, '0', STR_PAD_LEFT),

                'postURL'           => "https://en6pq3rsm1ve7.x.pipedream.net",

            );

         $api = wp_remote_post( $mpay_adr, array(
        'headers'     => array( 'Content-Type' => 'application/json'),
        'body' =>     json_encode($mpay_args )
    ) );

         $api_res = json_decode($api['body'], true);

    if ($api_res['responseCode'] == '0'){

         $status="processing";
}

else if ($api_res['responseCode'] == 'PE') {

    $status="pending";
}

else {

    $status="cancelled";
}
        // The key slug defined for your action button
        $action_slug = 'invoice';
       $orderid= $order->get_id();
       $actions[$action_slug] = array(
            'url'       => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status='.$status.'&order_id=' . $orderid ), 'woocommerce-mark-order-status' ),
            'name'      => __( 'Get Payment Status', 'woocommerce' ),
            'action'    => $action_slug,
        );
    }
    return $actions;
}


add_action( 'admin_head', 'add_custom_order_status_actions_button_css' );
function add_custom_order_status_actions_button_css() {
    $action_slug = "invoice"; // The key slug defined for your action button

    echo '<style>.wc-action-button-'.$action_slug.'::after { font-family: woocommerce !important; content: "e009" !important; }</style>';
}

However this function is wp_remote_post is triggered whenever I refresh the page, how can I make this action only to happen when the button is pressed…

Advertisement

Answer

What you need is to add a custom Ajax function where you will make your api call to change the order status, for “pending” orders… So your code is going to be a bit different:

add_filter( 'woocommerce_admin_order_actions', 'add_check_pg4_order_status_actions_button', 100, 2 );
function add_check_pg4_order_status_actions_button( $actions, $order ) {
    if ( $order->has_status( array('pending') ) ) {
        $actions['cpg4status'] = array(
            'url'    => wp_nonce_url(
                admin_url('admin-ajax.php?action=check_pg4status&order_id=' . $order->get_id() ),
                'check-pg-4-status'
            ),
            'name'   => __( 'Check Payment Status', 'woocommerce' ),
            'action' => 'cpg4status',
        );
    }
    return $actions;
}

add_action( 'wp_ajax_check_pg4status', 'trigger_check_pg4status' );
function trigger_check_pg4status() {
    if ( current_user_can('edit_shop_orders') && check_admin_referer('check-pg-4-status') &&
    isset($_GET['order_id']) && get_post_type( absint( wp_unslash($_GET['order_id']) ) ) === 'shop_order' ) {
        $order_id = absint( wp_unslash($_GET['order_id']) );
        $order    = wc_get_order($order_id);

        if( is_a($order, 'WC_Order') && $order->has_status( array( 'pending' ) ) ) {
            $settings    = (array) get_option('pay_settings');

            $mpay_url    = "https://www.apiurl.com";
            $hash_key    = $settings['secret'];
            $merchant_id = $settings['merchant_id'];
            $order_total = (float) $order->get_total();

            $mid         = str_pad( $merchant_id, 10, '0', STR_PAD_LEFT );
            $invno       = str_pad( $order_id, 20, '0', STR_PAD_LEFT );
            $amt         = str_pad( $order_total * 100, 12, '0', STR_PAD_LEFT );
            $post_url    = "https://en6pq3rsm1ve7.x.pipedream.net";

            $shash       = strtoupper( hash( 'sha256', $hash_key . "Continue" . $mid . $invno . $amt ) );
            $mpay_args   = ['secureHash' => $shash, 'mid' => $mid, 'invno' => $invno, 'amt' => $amt, 'postURL' => $post_url ];

            $api = wp_remote_post( $mpay_url, array(
                'headers' => array( 'Content-Type' => 'application/json'),
                'body' => json_encode( $mpay_args ),
            ) );

            $response = json_decode( $api['body'], true );

            if ( $response['responseCode'] == '0' ){
                $status = "processing";         }
            else if ( $response['responseCode'] != 'PE' ) {
                $status = "pending"; // <== The order is already in "pending" status, we will not update it.
            }
            else {
                $status = "cancelled";
            }

            // Except for "pending" status as the order is already in "pending" status
            if ( $status != "pending" ) {
                $order->update_status( $status, 'Payment gateway check', true );
            }
        }
    }
    wp_safe_redirect( ( wp_get_referer() ? wp_get_referer() : admin_url( 'edit.php?post_type=shop_order' ) ) . '&order_checked='.$order_id );
    exit;
}

add_action( 'admin_head', 'styling_pg4status_button' );
function styling_pg4status_button() {
    global $pagenow;

    $action_slug = "cpg4status"; // The key slug defined for your action button

    if( $pagenow === 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] === 'shop_order' ) {
        echo '<style>.wc-action-button-'.$action_slug.'::after { font-family: woocommerce !important; content: "e009" !important; }</style>';
    }
}

Tested and works (Assuming that I can’t test your external api call).

Related: Custom action button in WooCommerce admin orders that send an email

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement