Hi there, I'm trying to build a very simple plugin for woocommerce to show some information about delivery without taxes. The diference for the other methods is the extra HTML field.
I read a lot of the documentation but I think there is something miss on the configuration. The admin it seems working. But the method didn't appear on checkout screen. The code is below:
<?php
if ( ! defined( 'WPINC' ) ) {
die('security by preventing any direct access to your plugin file');
}
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
function shipping_delivery_info() {
if (!class_exists('shipping_delivery_info')) {
class shipping_delivery_info extends WC_Shipping_Method {
public function __construct( $instance_id = 0) {
$this->id = 'shipping_delivery_info';
$this->instance_id = absint( $instance_id );
$this->method_title = __('Shipping Delivery Info', 'shipping_delivery_info');
$this->method_description = __('A Woocommerce custom shipping method plugin, that shows ' .
'some shipping information to costumer, like free shipping but with HTML field.',
'shipping_delivery_info');
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
}
/**
* Load the settings API
*/
function init() {
// Load the settings
$this->init_form_fields();
$this->init_settings();
$this->enabled = $this->get_option( 'enabled' );
$this->title = $this->get_option( 'title' );
$this->info = $this->get_option( 'info' );
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
function init_form_fields() {
$this->instance_form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'shipping_delivery_info'),
'type' => 'checkbox',
'label' => __( 'Enable this shipping method', 'shipping_delivery_info'),
'default' => 'yes',
),
'title' => array(
'title' => __('Title', 'shipping_delivery_info'),
'type' => 'text',
'description' => __( 'The title to be displayed during checkout.', 'shipping_delivery_info' ),
'default' => __('Shipping Information', 'shipping_delivery_info'),
),
'info' => array(
'title' => __('Information', 'shipping_delivery_info'),
'type' => 'text',
'description' => __( 'Information about delivery and its taxes.', 'shipping_delivery_info' ),
'default' => __('Insert here some HTML.'),
),
);
}
}
}
}
add_action('woocommerce_shipping_init', 'shipping_delivery_info');
function add_shipping_delivery_info($methods)
{
$methods['shipping_delivery_info'] = 'shipping_delivery_info';
return $methods;
}
add_filter('woocommerce_shipping_methods', 'add_shipping_delivery_info');
function shipping_delivery_info_message($posted)
{
$packages = WC()->shipping->get_packages();
$chosen_methods = WC()->session->get('chosen_shipping_methods');
if (is_array($chosen_methods) && in_array('shipping_delivery_info', $chosen_methods)) {
foreach ($packages as $i => $package) {
if ($chosen_methods[$i] != "shipping_delivery_info") {
continue;
}
$shipping_delivery_info = new shipping_delivery_info();
$message = $shipping_delivery_info->settings['info'];
return $message;
/*$messageType = "info";
wc_add_notice($message, $messageType);*/
}
}
}
add_action('woocommerce_review_order_before_cart_contents', 'shipping_delivery_info_message', 10);
add_action('woocommerce_after_checkout_validation', 'shipping_delivery_info_message', 10);
}
You need to add the calculate_shipping function to your class
/**
* function calculate_shipping.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping( $package = array() ) {
$rate = array(
'id' => 'My Method id',
'label' => 'New method',
'cost' => 0,
'calc_tax' => 'per_item'
);
$this->add_rate( $rate );
}
}
Anyway, i think you don't need to add a new shipping method just to show some info at the cart, instead you can use these actions:
add_action( 'woocommerce_review_order_before_submit', 'add_tracking_notification', 12 );
add_action('woocommerce_proceed_to_checkout', 'add_tracking_notification');
function add_tracking_notification() {
echo '<h5 style="margin-bottom:10px">This is a custom message</h5>';
}
Related
I have a custom gateway, I am new to the custom plugins for woocommerce, now my problem I have is that I am able to redirect to my payment gateway but in my payment gateway (HTML) how do I redirect back after payment was made? I don't understand the whole process as yet, I know once payment is selected then I can redirect to my custom payment gateway but the confusing part is returning from payment gateway to woocommerce to say it was a success or not
<?php
/**
* Plugin Name: Woocommerce CloudCart Payment Gateway
* Plugin URI: http://cloudcart.online
* Description: Payment Gateway to use CloudCart points.
* Author: Cornelis Kuijpers
* Author URI: http://kuijpersconsulting.co.za
* Version: 1.0.1
*
*/
add_action('plugins_loaded', 'init_Cloudcart', 0);
function init_Cloudcart() {
if ( ! class_exists( 'WC_Payment_Gateway' ) ) return;
class woocommerce_Cloudcart extends WC_Payment_Gateway {
public function __construct() {
global $woocommerce;
$this->id = 'Cloudcart';
$this->method_title = __('Cloudcart', 'Cloudcart-chearaan-woo');
$this->icon = plugins_url( 'Cloudcart.png', __FILE__ );
$this->has_fields = false;
$this->notify_url = str_replace( 'https:', 'http:', add_query_arg( 'wc-api', 'woocommerce_Cloudcart', home_url( '/' ) ) );
// Load the form fields.
$this->init_form_fields();
// Load the settings.
$this->init_settings();
// Define user set variables
$this->Cloudcarturl = $this->settings['Cloudcarturl'];
$this->title = $this->settings['title'];
$this->description = $this->settings['description'];
$this->merchantid = $this->settings['merchantid'];
$this->hashKey = $this->settings['hashKey'];
$this->transactionDate = date('Y-m-d H:i:s O');
$this->woo_version = $this->get_woo_version();
// Actions
add_action('init', array(&$this, 'successful_request'));
add_action('woocommerce_api_woocommerce_Cloudcart', array( &$this, 'successful_request' ));
add_action('woocommerce_receipt_Cloudcart', array(&$this, 'receipt_page'));
if ( version_compare( WOOCOMMERCE_VERSION, '2.0.0', '>=' ) ) {
add_action('woocommerce_update_options_payment_gateways_' . $this->id, array( &$this, 'process_admin_options' ));
} else {
add_action('woocommerce_update_options_payment_gateways', array( &$this, 'process_admin_options' ));
}
}
/**
* Initialise Gateway Settings Form Fields
*/
function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable:', 'Cloudcart-chearaan-woo' ),
'type' => 'checkbox',
'label' => __( 'Enable Cloudcart', 'Cloudcart-chearaan-woo' ),
'default' => 'yes'
),
'Cloudcarturl' => array(
'title' => __( 'Test/Production:', 'Cloudcart-chearaan-woo' ),
'type' => 'checkbox',
'label' => __( 'Test', 'Cloudcart-chearaan-woo' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title:', 'Cloudcart-chearaan-woo' ),
'type' => 'text',
'description' => __( 'The title which the user sees during checkout.', 'Cloudcart-chearaan-woo' ),
'default' => __( 'Cloudcart Online Payment Gateway', 'Cloudcart-chearaan-woo' )
),
'description' => array(
'title' => __( 'Description:', 'Cloudcart-chearaan-woo' ),
'type' => 'textarea',
'description' => __( 'Description which the user sees during checkout.', 'Cloudcart-chearaan-woo' ),
'default' => __('Pay securely through Cloudcart\'s Secure Servers.', 'Cloudcart-chearaan-woo')
),
'merchantid' => array(
'title' => __( 'Merchant ID:', 'Cloudcart-chearaan-woo' ),
'type' => 'text',
'description' => __( 'Please enter your Merchant ID as provided by Cloudcart.', 'Cloudcart-chearaan-woo' ),
'default' => ''
),
'hashKey' => array(
'title' => __( 'Merchant hashKey:', 'Cloudcart-chearaan-woo' ),
'type' => 'text',
'description' => __( 'Please enter your Merchant hashKey as provided by Cloudcart.', 'Cloudcart-chearaan-woo' ),
'default' => ''
)
);
}
public function admin_options() {
?>
<h3>Cloudcart</h3>
<p><?php _e('Cloudcart works by sending the user to Cloudcart to enter their payment information.', 'Cloudcart-chearaan-woo'); ?></p>
<table class="form-table">
<?php
// Generate the HTML For the settings form.
$this->generate_settings_html();
?>
</table><!--/.form-table-->
<?php
} // End admin_options()
/**
* There are no payment fields, but we want to show the description if set.
**/
function payment_fields() {
if ($this->description) echo wpautop(wptexturize($this->description));
}
/**
* Generate the button link
**/
public function generate_Cloudcart_form( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
if ($this->Cloudcarturl == "yes"){
$Cloudcart_adr = "https://ckconsulting.ddns.net/API/CloudCart/";
}else{
$Cloudcart_adr = "https://ckconsulting.ddns.net/API/CloudCart/";
}
$sHash = strtoupper(hash('sha256', $this->hashKey."Continue".str_pad($this->merchantid, 10, '0', STR_PAD_LEFT).str_pad($order->id, 20, '0', STR_PAD_LEFT).str_pad(($order->order_total*100), 12, '0', STR_PAD_LEFT)));
$Cloudcart_args = array(
'secureHash' => $sHash,
'mid' => str_pad($this->merchantid, 10, '0', STR_PAD_LEFT),
'invno' => str_pad($order->id, 20, '0', STR_PAD_LEFT),
'amt' => str_pad(($order->order_total*100), 12, '0', STR_PAD_LEFT),
'desc' => str_pad("Order No ".$order_id, 255, ' ', STR_PAD_RIGHT),
'postURL' => $this->notify_url,
'phone' => $order->billing_phone,
'email' => $order->billing_email,
'param' => 'WC|V1'
);
$Cloudcart_args_array = array();
foreach ($Cloudcart_args as $key => $value) {
$Cloudcart_args_array[] = '<input type="hidden" name="'.$key.'" value="'. $value .'" /><br>';
}
wc_enqueue_js('
jQuery(function(){
jQuery("body").block(
{
message: "<img src=\"'.$woocommerce->plugin_url().'/images/uploading.gif\" alt=\"Redirecting…\" style=\"float:left; margin-right: 10px;\" />'.__('Thank you for your order. We are now redirecting you to Cloudcart to make payment.', 'Cloudcart-chearaan-woo').'",
overlayCSS:
{
background: "#fff",
opacity: 0.5
},
css: {
padding: 18,
textAlign: "center",
color: "#555",
border: "2px solid #aaa",
backgroundColor:"#fff",
cursor: "wait",
lineHeight: "30px"
}
});
jQuery("#submit_Cloudcart_payment_form").click();
});
');
return '<form action="'.$Cloudcart_adr.'" method="post">
' . implode('', $Cloudcart_args_array) . '
<input type="submit" class="button-alt" id="submit_Cloudcart_payment_form" value="'.__('Pay via Cloudcart', 'Cloudcart-chearaan-woo').'" /> <a class="button cancel" href="'.$order->get_cancel_order_url().'">'.__('Cancel order & restore cart', 'Cloudcart-chearaan-woo').'</a>
</form>';
}
/**
* Process the payment and return the result
**/
function process_payment( $order_id ) {
$order = new WC_Order( $order_id );
echo get_permalink(get_option('woocommerce_pay_page_id'));
if($this->woo_version >= 2.1){
$redirect = $order->get_checkout_payment_url( true );
}else if( $this->woo_version < 2.1 ){
$redirect = add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(get_option('woocommerce_pay_page_id'))));
}else{
$redirect = add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(get_option('woocommerce_pay_page_id'))));
}
return array(
'result' => 'success',
'redirect' => $redirect
);
}
/**
* receipt_page
**/
function receipt_page( $order ) {
echo '<p>'.__('Please click the button below to pay with Cloudcart.', 'Cloudcart-chearaan-woo').'</p>';
echo $this->generate_Cloudcart_form( $order );
}
/**
* Server callback was valid, process callback (update order as passed/failed etc).
**/
function successful_request($Cloudcart_response) {
global $woocommerce;
echo 'Hello from the other side';
if (isset($_GET['wc-api']) && $_GET['wc-api'] == 'woocommerce_Cloudcart') {
/** need to trim from result **/
$Url_result = $_GET['result'];
$order = new WC_Order( (int) substr($Url_result,7,20) );
$tranID = (int)substr($Url_result,1,6);
if (substr($Url_result,0,1) == '0'){
$r_status = 0;
}else{
$r_status = 33;
}
/*
$order = new WC_Order( (int) $_POST['invno'] );
$r_status = (int) $_POST['result'];
*/
if ($r_status == '0' ){
$order->payment_complete();
$order->add_order_note('Cloudcart Payment was SUCCESSFUL '.'<br>AuthCode is ' . $tranID);
wp_redirect( $this->get_return_url($order) ); exit;
//wp_redirect( $this->order->get_checkout_order_received_url() ); exit;
}else{
$order->update_status('failed', sprintf(__('Cloudcart Payment Failed. Error Communicating with Bank.', 'Cloudcart-chearaan-woo') ) );
wp_redirect($order->get_cancel_order_url()); exit;
}
}
}
function get_woo_version() {
// If get_plugins() isn't available, require it
if ( ! function_exists( 'get_plugins' ) )
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
// Create the plugins folder and file variables
$plugin_folder = get_plugins( '/woocommerce' );
$plugin_file = 'woocommerce.php';
// If the plugin version number is set, return it
if ( isset( $plugin_folder[$plugin_file]['Version'] ) ) {
return $plugin_folder[$plugin_file]['Version'];
} else {
// Otherwise return null
return NULL;
}
}
}
}
/**
* Add the gateway to WooCommerce
**/
function add_Cloudcart( $methods ) {
$methods[] = 'woocommerce_Cloudcart'; return $methods;
}
add_filter('woocommerce_payment_gateways', 'add_Cloudcart' );
Using Woocommerce, I want to force a shipping method when a certain valid coupon is applied at the cart/checkout phase.
Below my code. It extends WC_Shipping_Method, gets the whole woocommerce coupon list, let admin to select one or more, save them and then, when a costumer applies one of those chosen coupons checking out, forces to use only one this shipping method.
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
/* Custom LocalPickup Class */
class WC_Shipping_LocalPickUp_On_Coupon extends WC_Shipping_Method {
public $requires = '';
public function __construct( $instance_id = 0 ) {
$this->id = 'localpickup_on_coupon';
$this->instance_id = absint( $instance_id );
$this->method_title = __( 'Pickup with Coupon', 'Valeo' );
$this->method_description = __( 'Pickup with Coupon', 'Valeo' );
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
/*Getting Coupon List */
$args = array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'asc',
'post_type' => 'shop_coupon',
'post_status' => 'publish',
);
$coupons = get_posts( $args );
$this->list = [];
foreach($coupons as $item){
$this->list[$item->post_name] = $item->post_title;
}
$this->init();
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
public function init() {
$this->init_form_fields();
$this->init_settings();
$this->title = $this->get_option( 'title' );
$this->requires = $this->get_option( 'requires' );
}
public function init_form_fields() {
$this->instance_form_fields = array(
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => $this->method_title,
'desc_tip' => true,
),
'requires' => array(
'title' => __( 'Il ritiro in sede richiede...', 'Valeo' ),
'type' => 'multiselect',
'class' => 'valeo_multiselect',
'default' => '',
'options' => $this->list
),
);
}
public function is_available( $package ) {
$has_coupon = false;
$coupons = WC()->cart->get_coupons();
if(!empty($coupons)) {
$couponKey = array_keys($coupons)[0];
if ( in_array( $couponKey, $this->requires ) ) {
if ( $coupons ) {
foreach ( $coupons as $code => $coupon ) {
if ( $coupon->is_valid() ) {
$has_coupon = true;
break;
}
}
}
}
}
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $has_coupon, $package, $this );
}
public function calculate_shipping( $package = array() ) {
$rate = array(
'id' => $this->get_rate_id(),
'label' => $this->title,
'cost' => 0,
'taxes' => 0,
'package' => $package,
);
$this->add_rate($rate);
do_action( 'woocommerce_' . $this->id . '_shipping_add_rate', $this, $rate );
}
}
add_filter( 'woocommerce_shipping_methods', 'register_devso_method' );
function register_devso_method( $methods ) {
$methods[ 'localpickup_on_coupon' ] = 'WC_Shipping_LocalPickUp_On_Coupon';
return $methods;
}
}
Here the filter that checks if customer has inserted the chosen coupon/s and (in a "bad" way) removes all woocommerce package rates but the one I declared in the class.
function filter_woocommerce_package_rates( $array ) {
$check = FALSE;
foreach($array as $index => $value){
if(strpos($index, 'localpickup_on_coupon') !== false) { $check = TRUE; }
}
if($check){
foreach($array as $index => $value){
if(!(strpos($index, 'localpickup_on_coupon') !== false)) { unset($array[$index]); }
}
}
return $array;
};
// add the filter
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 1 );
Is there a better way to do this?
I have a WC payment gateway which was build and working until WP version 4.1. Today I started testing it on WP 4.9.8 and WC 3.5.1.
When I try to complete purchase the payment gateway is not taking me to the payment screen to fill credit card details. It get stuck on redirection state.
Hope someone can help me out to solve this.
Below the image reference and the code I am using:
<?php
/**
* Plugin Name: CustomPaymentGateway
*/
add_action('plugins_loaded', 'init_mpay', 0);
function init_mpay() {
if ( ! class_exists( 'WC_Payment_Gateway' ) ) return;
class woocommerce_mpay extends WC_Payment_Gateway {
public function __construct() {
global $woocommerce;
$this->id = 'mpay';
$this->method_title = __('MPay', 'mpay-chearaan-woo');
$this->icon = plugins_url( 'mpay.png', __FILE__ );
$this->has_fields = false;
$this->notify_url = str_replace( 'https:', 'http:', add_query_arg( 'wc-api', 'woocommerce_mpay', home_url( '/' ) ) );
// Load the form fields.
$this->init_form_fields();
// Load the settings.
$this->init_settings();
// Define user set variables
$this->mpayurl = $this->settings['mpayurl'];
$this->title = $this->settings['title'];
$this->description = $this->settings['description'];
$this->merchantid = $this->settings['merchantid'];
$this->hashKey = $this->settings['hashKey'];
$this->transactionDate = date('Y-m-d H:i:s O');
$this->woo_version = $this->get_woo_version();
// Actions
add_action('init', array(&$this, 'successful_request'));
add_action('woocommerce_api_woocommerce_mpay', array( &$this, 'successful_request' ));
add_action('woocommerce_receipt_mpay', array(&$this, 'receipt_page'));
if ( version_compare( WOOCOMMERCE_VERSION, '2.0.0', '>=' ) ) {
add_action('woocommerce_update_options_payment_gateways_' . $this->id, array( &$this, 'process_admin_options' ));
} else {
add_action('woocommerce_update_options_payment_gateways', array( &$this, 'process_admin_options' ));
}
}
/**
* Initialise Gateway Settings Form Fields
*/
function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable:', 'mpay-chearaan-woo' ),
'type' => 'checkbox',
'label' => __( 'Enable MPay', 'mpay-chearaan-woo' ),
'default' => 'yes'
),
'mpayurl' => array(
'title' => __( 'UAT/Production:', 'mpay-chearaan-woo' ),
'type' => 'checkbox',
'label' => __( 'UAT', 'mpay-chearaan-woo' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title:', 'mpay-chearaan-woo' ),
'type' => 'text',
'description' => __( 'The title which the user sees during checkout.', 'mpay-chearaan-woo' ),
'default' => __( 'MPay Online Payment Gateway', 'mpay-chearaan-woo' )
),
'description' => array(
'title' => __( 'Description:', 'mpay-chearaan-woo' ),
'type' => 'textarea',
'description' => __( 'Description which the user sees during checkout.', 'mpay-chearaan-woo' ),
'default' => __('Pay securely through MPay\'s Secure Servers.', 'mpay-chearaan-woo')
),
'merchantid' => array(
'title' => __( 'Merchant ID:', 'mpay-chearaan-woo' ),
'type' => 'text',
'description' => __( 'Please enter your Merchant ID as provided by MPay.', 'mpay-chearaan-woo' ),
'default' => ''
),
'hashKey' => array(
'title' => __( 'Merchant hashKey:', 'mpay-chearaan-woo' ),
'type' => 'text',
'description' => __( 'Please enter your Merchant hashKey as provided by MPay.', 'mpay-chearaan-woo' ),
'default' => ''
)
);
}
public function admin_options() {
?>
<h3>MPay</h3>
<p><?php _e('MPay works by sending the user to MPay to enter their payment information.', 'mpay-chearaan-woo'); ?></p>
<table class="form-table">
<?php
// Generate the HTML For the settings form.
$this->generate_settings_html();
?>
</table><!--/.form-table-->
<?php
} // End admin_options()
/**
* There are no payment fields, but we want to show the description if set.
**/
function payment_fields() {
if ($this->description) echo wpautop(wptexturize($this->description));
}
/**
* Generate the button link
**/
public function generate_mpay_form( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
if ($this->mpayurl == "yes"){
$mpay_adr = "https://pcimdex.mpay.my/mdex2/payment/eCommerce";
}else{
$mpay_adr = "https://www.mdex.my/mdex/payment/eCommerce";
}
$sHash = strtoupper(hash('sha256', $this->hashKey."Continue".str_pad($this->merchantid, 10, '0', STR_PAD_LEFT).str_pad($order->id, 20, '0', STR_PAD_LEFT).str_pad(($order->order_total*100), 12, '0', STR_PAD_LEFT)));
$mpay_args = array(
'secureHash' => $sHash,
'mid' => str_pad($this->merchantid, 10, '0', STR_PAD_LEFT),
'invno' => str_pad($order->id, 20, '0', STR_PAD_LEFT),
'amt' => str_pad(($order->order_total*100), 12, '0', STR_PAD_LEFT),
'desc' => str_pad("Order No ".$order_id, 255, ' ', STR_PAD_RIGHT),
'postURL' => $this->notify_url,
'phone' => $order->billing_phone,
'email' => $order->billing_email,
'param' => 'WC|V1'
);
$mpay_args_array = array();
foreach ($mpay_args as $key => $value) {
$mpay_args_array[] = '<input type="hidden" name="'.$key.'" value="'. $value .'" /><br>';
}
wc_enqueue_js('
jQuery(function(){
jQuery("body").block(
{
message: "<img src=\"'.$woocommerce->plugin_url().'/images/uploading.gif\" alt=\"Redirecting…\" style=\"float:left; margin-right: 10px;\" />'.__('Thank you for your order. We are now redirecting you to MPay to make payment.', 'mpay-chearaan-woo').'",
overlayCSS:
{
background: "#fff",
opacity: 0.5
},
css: {
padding: 18,
textAlign: "center",
color: "#555",
border: "2px solid #aaa",
backgroundColor:"#fff",
cursor: "wait",
lineHeight: "30px"
}
});
jQuery("#submit_mpay_payment_form").click();
});
');
return '<form action="'.$mpay_adr.'" method="post">
' . implode('', $mpay_args_array) . '
<input type="submit" class="button-alt" id="submit_mpay_payment_form" value="'.__('Pay via MPay', 'mpay-chearaan-woo').'" /> <a class="button cancel" href="'.$order->get_cancel_order_url().'">'.__('Cancel order & restore cart', 'mpay-chearaan-woo').'</a>
</form>';
}
/**
* Process the payment and return the result
**/
function process_payment( $order_id ) {
$order = new WC_Order( $order_id );
if($this->woo_version >= 2.1){
$redirect = $order->get_checkout_payment_url( true );
}else if( $this->woo_version < 2.1 ){
$redirect = add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(get_option('woocommerce_pay_page_id'))));
}else{
$redirect = add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(get_option('woocommerce_pay_page_id'))));
}
return array(
'result' => 'success',
'redirect' => $redirect
);
}
/**
* receipt_page
**/
function receipt_page( $order ) {
echo '<p>'.__('Please click the button below to pay with MPay.', 'mpay-chearaan-woo').'</p>';
echo $this->generate_mpay_form( $order );
}
/**
* Server callback was valid, process callback (update order as passed/failed etc).
**/
function successful_request($mpay_response) {
global $woocommerce;
if (isset($_GET['wc-api']) && $_GET['wc-api'] == 'woocommerce_mpay') {
/** need to trim from result **/
$Url_result = $_GET['result'];
$order = new WC_Order( (int) substr($Url_result,7,20) );
$tranID = (int)substr($Url_result,1,6);
if (substr($Url_result,0,1) == '0'){
$r_status = 0;
}else{
$r_status = 33;
}
/*
$order = new WC_Order( (int) $_POST['invno'] );
$r_status = (int) $_POST['result'];
*/
if ($r_status == '0' ){
$order->payment_complete();
$order->add_order_note('MPay Payment was SUCCESSFUL '.'<br>AuthCode is ' . $tranID);
wp_redirect( $this->get_return_url($order) ); exit;
//wp_redirect( $this->order->get_checkout_order_received_url() ); exit;
}else{
$order->update_status('failed', sprintf(__('MPay Payment Failed. Error Communicating with Bank.', 'mpay-chearaan-woo') ) );
wp_redirect($order->get_cancel_order_url()); exit;
}
}
}
function get_woo_version() {
// If get_plugins() isn't available, require it
if ( ! function_exists( 'get_plugins' ) )
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
// Create the plugins folder and file variables
$plugin_folder = get_plugins( '/woocommerce' );
$plugin_file = 'woocommerce.php';
// If the plugin version number is set, return it
if ( isset( $plugin_folder[$plugin_file]['Version'] ) ) {
return $plugin_folder[$plugin_file]['Version'];
} else {
// Otherwise return null
return NULL;
}
}
}
}
/**
* Add the gateway to WooCommerce
**/
function add_mpay( $methods ) {
$methods[] = 'woocommerce_mpay'; return $methods;
}
add_filter('woocommerce_payment_gateways', 'add_mpay' );
I have successfully created a new shipping method and given it support for shipping zones. However when I come to select the method from the dropdown to add it to the zone it does not appear in the 'selected methods list'.
I recorded a screencast gif to demonstrate:
I can't for the life of me figure out why it's not working. It works fine if I select one of the standard methods (Screencast GIF)
Anyone know what's going on here and how to get it to work?
Here's the code that I have from this official thread: Shipping Method API:
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
function request_a_shipping_quote_init() {
if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
class WC_Request_Shipping_Quote_Method extends WC_Shipping_Method {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
public function __construct() {
$this->id = 'request_a_shipping_quote'; // Id for your shipping method. Should be uunique.
$this->method_title = __( 'Request a Shipping Quote' ); // Title shown in admin
$this->method_description = __( 'Shipping method to be used where the exact shipping amount needs to be quoted' ); // Description shown in admin
$this->title = "Request a Shipping Quote"; // This can be added as an setting but for this example its forced.
$this->supports = array(
'shipping-zones'
);
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
$this->init_settings(); // This is part of the settings API. Loads settings you previously init.
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable', 'dc_raq' ),
'type' => 'checkbox',
'description' => __( 'Enable this shipping method.', 'dc_raq' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'dc_raq' ),
'type' => 'text',
'description' => __( 'Title to be displayed on site', 'dc_raq' ),
'default' => __( 'Request a Quote', 'dc_raq' )
),
);
}
/**
* calculate_shipping function.
*
* #access public
*
* #param mixed $package
*
* #return void
*/
public function calculate_shipping( $packages = array() ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '0.00',
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate( $rate );
}
}
}
}
add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );
function request_shipping_quote_shipping_method( $methods ) {
$methods['request_shipping_quote_shipping_method'] = 'WC_Request_Shipping_Quote_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
}
The method key on "woocommerce_shipping_methods" should match the shipping method id
In your case:
You should change
function request_shipping_quote_shipping_method( $methods ) {
$methods['request_shipping_quote_shipping_method'] = 'WC_Request_Shipping_Quote_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
To:
function request_shipping_quote_shipping_method( $methods ) {
$methods['request_a_shipping_quote'] = 'WC_Request_Shipping_Quote_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
Change this line
public function calculate_shipping( $package ) {
to this line
public function calculate_shipping( $package = array() ) {
After I trying to use code in question and fix all errors that I found in comments to these post I still had some problems with it. For example I can't edit shipping method after even I successfully added it to shipping zone.
Finally I got desired code that working for me after edit standard free shipping woocoommerce method. Hope it will save time for someone.
function request_a_shipping_quote_init() {
if ( ! class_exists( 'Imp_WC_Shipping_Local_Pickup' ) ) {
class Imp_WC_Pickup_Shipping_Method extends WC_Shipping_Method {
/**
* Constructor.
*
* #param int $instance_id
*/
public function __construct( $instance_id = 0 ) {
$this->id = 'imp_pickup_shipping_method';
$this->instance_id = absint( $instance_id );
$this->method_title = __( "Самовывоз из точки выдачи ( MO г. Дзержинский )", 'imp' );
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
}
/**
* Initialize custom shiping method.
*/
public function init() {
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option( 'title' );
// Actions
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* Calculate custom shipping method.
*
* #param array $package
*
* #return void
*/
public function calculate_shipping( $package = array() ) {
$this->add_rate( array(
'label' => $this->title,
'package' => $package,
) );
}
/**
* Init form fields.
*/
public function init_form_fields() {
$this->instance_form_fields = array(
'title' => array(
'title' => __( 'Самовывоз из точки выдачи ( MO г. Дзержинский )', 'imp' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Самовывоз из точки выдачи ( MO г. Дзержинский )', 'imp' ),
'desc_tip' => true,
),
);
}
}
}
}
add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );
function request_shipping_quote_shipping_method( $methods ) {
$methods['imp_pickup_shipping_method'] = 'Imp_WC_Pickup_Shipping_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
WC_Custom_Shipping_Method is an abstract class and you are trying to change its inherited method calculate_shipping which abstract classes don't allow.
Try doing it like this.
<?php
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
function request_a_shipping_quote_init() {
class Abs_Custom_Shipping extends WC_Shipping_Method{}
if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
class WC_Request_Shipping_Quote_Method extends Abs_Custom_Shipping {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
public function __construct() {
$this->id = 'request_a_shipping_quote'; // Id for your shipping method. Should be uunique.
$this->method_title = __( 'Request a Shipping Quote' ); // Title shown in admin
$this->method_description = __( 'Shipping method to be used where the exact shipping amount needs to be quoted' ); // Description shown in admin
$this->title = "Request a Shipping Quote"; // This can be added as an setting but for this example its forced.
$this->supports = array(
'shipping-zones'
);
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
$this->init_settings(); // This is part of the settings API. Loads settings you previously init.
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable', 'dc_raq' ),
'type' => 'checkbox',
'description' => __( 'Enable this shipping method.', 'dc_raq' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'dc_raq' ),
'type' => 'text',
'description' => __( 'Title to be displayed on site', 'dc_raq' ),
'default' => __( 'Request a Quote', 'dc_raq' )
),
);
}
/**
* calculate_shipping function.
*
* #access public
*
* #param mixed $package
*
* #return void
*/
public function calculate_shipping( $packages = array() ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '0.00',
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate( $rate );
}
}
}
}
add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );
function request_shipping_quote_shipping_method( $methods ) {
$methods['request_shipping_quote_shipping_method'] = 'WC_Request_Shipping_Quote_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
}
( extend the shipping method into a child class, then extend the child class into a grandchild class where you can modify the calculate_shipping method ).
Hope it makes sense.
Regards
I had this issue and it was driving me crazy for a few days until, while looking through the Woocommerce code to understand what was happening, I discovered that when setting up the filter method for the woocommerce_shipping_methods, I needed to make the index of the entry that I was adding to this array the same as the ID property in my shipping method class. Once I did this, it added the shipping method fine and it showed it correctly for the zone. Previously, I had been adding the entry to the array in the filter method with no index, which works fine as far as WC seeing the method which was why it seemed ok. However, the code that saves the settings, uses the ID as the index to identify the shipping method. From other comments, I would imagine that this specific index was added in WC version 3. Hope this helps.
If your shipping method still seems not to work, you have to ensure that
instance_id must be defined in constructor, as in this snippet
public function __construct($instance_id = 0)
{
$this->instance_id = absint($instance_id);
// other lines follow
}
there is no stale data: remove transient data and clients' data (WooCommerce Settings > Status > Tools)
I'm working on a custom payment gateway for the WordPress plugin WooCommerce. I cannot seem to save the settings for the payment gateway. When I enter information into the fields and then click save, the page refreshes with all of the fields blank. What am I doing wrong?
Here is my code.
<?php
/**
* Plugin Name: Bitcoin WooCommerce Integration Made Easy
* Description: A Bitcoin processing plugin that integrates into WooCommerce made specifically for Bitcoin Publish.
* Version: 0.01
* Author: Cammy_the_block
*/
add_action( 'plugins_loaded', 'init_your_gateway_class' );
function init_your_gateway_class() {
class WC_Gateway_Your_Gateway extends WC_Payment_Gateway {
function __construct() {
$this->id = "Bitcoin WooCommerce Integration Gateway";
$this->method_title = "Bitcoin with BWCIME";
$this->method_description = "More later";
$this->init_form_fields();
$this->init_settings();
if ( version_compare( WOOCOMMERCE_VERSION, '2.0.0', '>=' ) ) {
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( &$this, 'process_admin_options' ) );
}
else {
add_action( 'woocommerce_update_options_payment_gateways', array( &$this, 'process_admin_options' ) );
}
}
function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable Cheque Payment', 'woocommerce' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Cheque Payment', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'title' => __( 'Customer Message', 'woocommerce' ),
'type' => 'textarea',
'default' => ''
)
);
}
}
function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
$productArray = array();
$x = 0;
foreach( $order->get_items() as $item_id => $item ) {
$productArray[x] = $order->get_product_from_item( $item );
$x++;
}
// Mark as on-hold (we're awaiting the cheque)
$order->update_status('on-hold',
__( 'Awaiting cheque payment. there are ' + $productArray.length + 'items', 'woocommerce' )
);
// Remove cart
$woocommerce->cart->empty_cart();
// Return thankyou redirect
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
}
}
function add_your_gateway_class ($methods ) {
$methods[] = 'WC_Gateway_Your_Gateway';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_your_gateway_class' );
?>
EDIT:
The add filter code runs add_your_gateway_class, which in turn causes it to run WC_Gateway_Your_Gateway.
you have to call them on the constructor after the init_settings();
$this->init_settings();
// Define user set variables
$this->access_key = $this->get_option( 'access_key' );
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
edit:
you also need another action/hook, just at the end of the constructor, no need to create that new function that you came up with:
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
edit 2:
sorry you already have it, my bad :p, dont realy know what happened there, glad its solved
The actual problem is your this->id="example_gateway": id is always case sensitive and it should be without space and lowercase.
Example:
function __construct() {
$this->id = "bitcoin_woocommerce_integration_gateway";
$this->method_title =( "Bitcoin with BWCIME", 'bitcoin_woocommerce_integration_gateway' );
$this->title = __( "Bitcoin with BWCIME", 'bitcoin_woocommerce_integration_gateway' );
$this->method_description = "More later";
//further as same as your code.....
}
I'm not completely sure how I fixed it, but I believe it had to do with adding the function admin_options().
public function admin_options() {
?>
<h3><?php _e('Bitcoin Payment', 'woothemes'); ?></h3>
<p><?php _e('Message!.', 'woothemes'); ?></p>
<table class="form-table">
<?php
// Generate the HTML For the settings form.
$this->generate_settings_html();
?>
</table>
<?php
}
EDIT: I'm not sure what causes it but you have to clear the plugin's settings by interfacing with the database. The easy way to do this is to change the ID of the plugin. I'm not actually sure where the settings are stored in the database.