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