WooCommerce custom payment method - wordpress

I have to add a custom payment method to woocommerce.
this payment method has well documented JSON APIs.
how do I add a custom payment method, and hook it to the API?

The woocommerce_payment_gateways filter lets you add custom payment gateways to woocommerce.
add_filter( 'woocommerce_payment_gateways', 'add_your_gateway_class' );
function add_your_gateway_class( $methods ) {
$methods[] = 'WC_Custom_PG';
return $methods;
}
Next you create a class that extends the WC_Payment_Gateway class. In its constructor, you need to set the unique id, title and description for your payment gateway. You also need to initialize the form fields and the payment gateway settings.
The payment gateway class needs to be defined in a function that is called by the plugins_loaded hook
add_action( 'plugins_loaded', 'init_wc_custom_payment_gateway' );
function init_wc_custom_payment_gateway(){
class WC_Custom_PG extends WC_Payment_Gateway {
function __construct(){
$this->id = 'wc_custom_pg';
$this->method_title = 'Custom Payment Gateway';
$this->title = 'Custom Payment Gateway';
$this->has_fields = true;
$this->method_description = 'Your description of the payment gateway';
//load the settings
$this->init_form_fields();
$this->init_settings();
$this->enabled = $this->get_option('enabled');
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option('description');
//process settings with parent method
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
}
public function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => 'Enable/Disable',
'type' => 'checkbox',
'label' => 'Enable Custom Payment Gateway',
'default' => 'yes'
),
'title' => array(
'title' => 'Method Title',
'type' => 'text',
'description' => 'This controls the payment method title',
'default' => 'Custom Payment Gatway',
'desc_tip' => true,
),
'description' => array(
'title' => 'Customer Message',
'type' => 'textarea',
'css' => 'width:500px;',
'default' => 'Your Payment Gateway Description',
'description' => 'The message which you want it to appear to the customer in the checkout page.',
)
);
}
function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
/****
Here is where you need to call your payment gateway API to process the payment
You can use cURL or wp_remote_get()/wp_remote_post() to send data and receive response from your API.
****/
//Based on the response from your payment gateway, you can set the the order status to processing or completed if successful:
$order->update_status('processing','Additional data like transaction id or reference number');
//once the order is updated clear the cart and reduce the stock
$woocommerce->cart->empty_cart();
$order->reduce_order_stock();
//if the payment processing was successful, return an array with result as success and redirect to the order-received/thank you page.
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
}
//this function lets you add fields that can collect payment information in the checkout page like card details and pass it on to your payment gateway API through the process_payment function defined above.
public function payment_fields(){
?>
<fieldset>
<p class="form-row form-row-wide">
<?php echo esc_attr($this->description); ?>
</p>
<div class="clear"></div>
</fieldset>
<?php
}
}
}
Once you activate your payment gateway plugin, you can enable the method in WooCommerce > Settings > Payments page.
For more information of payment gateway setup, you can visit : https://docs.woocommerce.com/document/payment-gateway-api/
You can either create this as a plugin or add the entire code to your theme's function.php file.

You need to write a plugin who embed your gateway API.
See more information on Woocomerce Documentation : Payment Gateway API
You can see further information about code/class/etc on the Woocomerce API Doc

thanks to both of you!
I also added these lines, otherwise I couldn't activate it:
add_filter('woocommerce_payment_gateways', 'weldpay_add_gateway_class');
function weldpay_add_gateway_class($gateways) {
$gateways[] = 'WC_Weldpay';
return $gateways;
}
there is the possibility to take information from the checkout, like items, name, surname, address, etc?

Related

How to have custom checkout fields in ajax checkout in woocommerce

I have an Ajax checkout on my woocommerce installation and I am trying to capture the custom fields on the checkout. I am using below code to try to capture the field called add_gift_box, the field appears fine on my checkout page.
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ($_POST['add_gift_box']) {
update_post_meta( $order_id, '_add_gift_box', esc_attr($_POST['add_gift_box']));
}
}
When I press "place order" button it creates a new order but the value of this field does not get saved in the database. I don't think even the hook gets fired. As I said everything is being handled by Ajax. The checkout page is one page checkout.
I need help sorting this out. Thanks in advance.
UPDATE
I am setting the field as follows:
add_action( 'woocommerce_after_checkout_billing_form', 'add_box_option_to_checkout' );
function add_box_option_to_checkout( $checkout ) {
woocommerce_form_field( 'add_gift_box', array(
'type' => 'radio',
'class' => array('add_gift_box form-row-wide'),
'label_class' => array('checkbox'),
'input_class' => array('input-checkbox'),
'required' => true,
'options' => array(
'option_1' => 'option1</br>' ,
'option_2' =>'option2</br>',
'option_3' =>'option3</br>',
'option_4' =>'option4</br>',
'option_5' =>'option5</br>',
'option_6' =>'option6</br>',
'option_7' =>'option7</br>',
),
'label' => __('Select Option'),
'placeholder' => __(''),
), $checkout->get_value( 'add_gift_box' ));
}
here is a plugin to add custom field on checkout page woocomerce https://wordpress.org/plugins/woo-custom-checkout-field/
or if you want to add by code you can follow codding from here
https://www.cloudways.com/blog/custom-field-woocommerce-checkout-page/
add_action('woocommerce_after_order_notes', 'customise_checkout_field');
function customise_checkout_field($checkout)
{
echo '<div id="customise_checkout_field"><h2>' . __('Heading') . '</h2>';
woocommerce_form_field('customised_field_name', array(
'type' => 'text',
'class' => array(
'my-field-class form-row-wide'
) ,
'label' => __('Customise Additional Field') ,
'placeholder' => __('Guidence') ,
'required' => true,
) , $checkout->get_value('customised_field_name'));
echo '</div>';
}
Do you have a plugin activated which creates the order by hooking into woocommerce_create_order filter? I don't see any other reason why add_gift_box isn't saved or why woocommerce_checkout_update_order_meta isn't firing.
The original code from includes/class-wc-checkout.php is
/**
* Action hook to adjust order before save.
* #since 3.0.0
*/
do_action( 'woocommerce_checkout_create_order', $order, $data );
// Save the order.
$order_id = $order->save();
do_action( 'woocommerce_checkout_update_order_meta', $order_id, $data );
So, you could create log files in your themes directory to see which hooks are firing like this:
add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
file_put_contents(__DIR__ . '/woocommerce_checkout_update_order_meta.log', 'woocommerce_checkout_update_order_meta fired for order id ' . $order_id);
});
add_action('woocommerce_checkout_create_order', function () {
file_put_contents(__DIR__ . '/woocommerce_checkout_create_order.log', 'woocommerce_checkout_create_order fired');
});

Get email from shipping adrdress in woocommerce

I'm developing a website where we sell digital products.
For requirement when the buyer ask to send the license to another email the buyer uses shipping address to enter the extra email.
so I added the email with the following function.
/*
* Add email to "shipping address"
*/
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_email'] = array(
'label' => __('Email Address', 'woocommerce'),
'placeholder' => _x('Email', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
The shipping form displays properly the email on the shipping section, but when order is completed I'm trying to catch that email and I haven't had it.
I'm using the following function to add the email to the recipient before the email is sent.
add_filter( 'woocommerce_email_recipient_customer_completed_order', 'my_email_shipping_filter_function', 20, 2);
function my_email_shipping_filter_function ($recipient, $order){
$shipping_email = get_post_meta( $order->id, '_shipping_email', true );
if ($shipping_email != '') {
$recipient = $recipient.', '.$shipping_email;
return $recipient;
}
}
But it is not working when the confirmation is sent, however when Im redirected to thank you page I can use the same function and display the shipping email.
Hope someone can help.

Woocommerce hide payment when is checked checkbox

I need to hide the payment method "Bank transfer" when checkbox is checked in checkout form.
My code for adding checkbox in checkout:
https://gist.github.com/thegdshop/3171026
add_action('woocommerce_after_order_notes', 'my_custom_checkout_field');
function my_custom_checkout_field( $checkout ) {
echo '<div id="my-new-field"><h3>'.__('My Checkbox: ').'</h3>';
woocommerce_form_field( 'my_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('I have read and agreed.'),
'required' => true,
), $checkout->get_value( 'my_checkbox' ));
echo '</div>';
}
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
global $woocommerce;
// Check if set, if its not set add an error.
if (!$_POST['my_checkbox'])
$woocommerce->add_error( __('Please agree to my checkbox.') );
}
add_action('woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta');
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ($_POST['my_checkbox']) update_post_meta( $order_id, 'My Checkbox', esc_attr($_POST['my_checkbox']));
}
In this situation you can use ajax. The approach is
Prehide the Bank transfer Payment on page load.
Write a code in jQuery to Unhide and hide 'Bank transfer' payment method.
That's it.
Let me know if that solves your problem.

Custom WooCommerce Gateway

I`m trying to develop a custom payment gateway for WooCommerce plugin, but I have a problem with the checkout page. What I want is to insert a form on the checkout final step page that is submitted automatically after 5 seconds.
My code is:
...
add_action('woocommerce_receipt_' . $this->id, array($this, 'receipt_page'));
add_action('woocommerce_api_wc_' . $this->id, array($this, 'handle_callback'));
}
function handle_callback() {
wp_die('handle_callback');
}
function receipt_page( $order )
{
echo "receipt page";
$this->generate_submit_form_elements( $order );
}
The problem is that "receipt_page" action is not triggered.
Thanks!
oh, its because you forgot to set the has_fields flag to true.
//after setting the id and method_title, set the has_fields to true
$this -> id = 'kiwipay';
$this -> method_title = 'KiwiPay';
$this->has_fields = true; // if you want credit card payment fields to show on the users checkout page
then in the process_payment function put this:
// Payload would look something like this.
$payload = array(
"amount" => $order.get_total(),
"reference" => $order->get_order_number(),
"orderid" => $order->id,
"return_url" => $this->get_return_url($order) //return to thank you page.
);
response = wp_remote_post( $environment_url, array(
'method' => 'POST',
'body' => http_build_query( $payload ),
'timeout' => 90,
'sslverify' => false,
) );
// Retrieve the body's response if no errors found
$response_body = wp_remote_retrieve_body( $response );
$response_headers = wp_remote_retrieve_headers( $response );
//use this if you need to redirect the user to the payment page of the bank.
$querystring = http_build_query( $payload );
return array(
'result' => 'success',
'redirect' => $environment_url . '?' . $querystring,
);

Add Tax Exempt form on checkout in woocommerce

I am trying to add a form to my checkout page so when a user clicks the 'Tax Exempt' checkbox, a textbox will popup and ask the user what the Tax Exempt Id number is.
I got all of that working great, and I even added the update_totals_on_change class to my form field so it will update the totals.
My next step was to add an action/filter on a method so when the update_totals_on_change executes, I can set the tax to 0 and then it will finish calculating the total.
Does anyone know which functions I can hook on to?
Looking at the checkout.js file in WooCommerce, they set the action to woocommerce_update_order_review for the ajax operation.
I tried following that but soon got lost.
I was thinking I could add some post data by hooking in to woocommerce_checkout_update_order_review
and then hooking in to woocommerce_before_calculate_totals to modify the tax stuff, but I have no idea what I need to modify.
Am I even on the right path?
Alright, I finally figured it out in case anyone is interested.
In my plugin, I made a form after the order notes by hooking in to this function: 'woocommerce_before_order_notes'
add_action('woocommerce_before_order_notes', array(&$this, 'taxexempt_before_order_notes') );
my 'taxexempt_before_order_notes' function contained:
function taxexempt_before_order_notes( $checkout ) {
echo '<div style="clear: both"></div>
<h3>Tax Exempt Details</h3>';
woocommerce_form_field( 'tax_exempt_checkbox', array(
'type' => 'checkbox',
'class' => array('tiri taxexempt'),array( 'form-row-wide', 'address-field' ),
'label' => __('Tax Exempt'),
), $checkout->get_value( 'tax_exempt_checkbox' ));
woocommerce_form_field( 'tax_exempt_name', array(
'type' => 'text',
'class' => array('form-row-first', 'tiri', 'taxexempt', 'textbox', 'hidden'),
'label' => __('Tax Exempt Name'),
), $checkout->get_value( 'tax_exempt_name' ));
woocommerce_form_field( 'tax_exempt_id', array(
'type' => 'text',
'class' => array('form-row-last', 'tiri', 'taxexempt', 'textbox', 'hidden', 'update_totals_on_change'),
'label' => __('Tax Exempt Id'),
), $checkout->get_value( 'tax_exempt_id' ));
}
Then the most important woocommerce function to hook was: 'woocommerce_checkout_update_order_review'
add_action( 'woocommerce_checkout_update_order_review', array(&$this, 'taxexempt_checkout_update_order_review' ));
function taxexempt_checkout_update_order_review( $post_data ) {
global $woocommerce;
$woocommerce->customer->set_is_vat_exempt(FALSE);
parse_str($post_data);
if ( isset($tax_exempt_checkbox) && isset($tax_exempt_id) && $tax_exempt_checkbox == '1' && !empty($tax_exempt_id))
$woocommerce->customer->set_is_vat_exempt(true);
}
I simply parsed out the $post_data that is the serialized form data from the checkout.js file in woocommerce and checked if my part of the form was filled out correctly.
If it was, then I would set the tax exempt for the user.
The accepted solution didn't work for me, but I modified it to use the following:
//=============================================================================
// ADD TAX EXEMPT CHECKMARK
// =============================================================================
add_action( 'woocommerce_after_order_notes', 'qd_tax_exempt');
function qd_tax_exempt( $checkout ) {
echo '<div id="qd-tax-exempt"><h3>'.__('Tax Exempt').'</h3>';
woocommerce_form_field( 'shipping_method_tax_exempt', array(
'type' => 'checkbox',
'class' => array(),
'label' => __('My organization is tax exempt.'),
'required' => false,
), $checkout->get_value( 'shipping_method_tax_exempt' ));
echo '</div>';
}
add_action( 'woocommerce_checkout_update_order_review', 'taxexempt_checkout_update_order_review');
function taxexempt_checkout_update_order_review( $post_data ) {
global $woocommerce;
$woocommerce->customer->set_is_vat_exempt(FALSE);
parse_str($post_data);
if ( isset($shipping_method_tax_exempt) && $shipping_method_tax_exempt == '1')
$woocommerce->customer->set_is_vat_exempt(true);
}
The key here is understanding that any field with a name that starts with shipping_method is going to inherit this updating order functionality (which was the part that didn't work for me). I found this answer at http://www.affectivia.com/blog/have-a-checkbox-on-the-checkout-page-which-updates-the-order-totals/
After a long search I found that there is a method for the cart object called remove_taxes() .
So, after setting a user meta for the tax exempt users, this cancels the tax totals.
function remove_tax_for_exempt( $cart ) {
global $current_user;
$ok_taxexp = get_the_author_meta( 'granted_taxexempt', $current_user->ID );
if ($ok_taxexp){ // now 0 the tax if user is tax exempt
$cart->remove_taxes();
}
return $cart;
}
add_action( 'woocommerce_calculate_totals', 'remove_tax_for_exempt' );
Because $cart->remove_taxes(); is deprecated. This is what I used instead.
I didn't have a form on the frontend, but have a user roll that is tax exempt. This was my solution.
Also worth noting that set_is_vat_exempt(true) also works in the US to set as tax exempt.
/**
* Set customer as tax exempt if user is a wholesale customer
*/
function remove_tax_for_exempt( $cart ) {
global $woocommerce;
if ( is_user_logged_in() && current_user_can( 'wholesale_customer' ) ) {
$woocommerce->customer->set_is_vat_exempt(true);
}
return $cart;
}
add_action( 'woocommerce_calculate_totals', 'remove_tax_for_exempt' );
Since this answer still pops up on google, I thought I'd share that setting the customer as tax exempt only works during checkout, if you need to edit the order on the back-end after it is placed and use the "recalculate" button, the taxes will still appear. Fortunately there is a hook for this as well:
function remove_tax_for_exempt($exempt, $order){
return $exempt || user_can($order->get_user_id(), 'wholesale_customer');
}
add_filter('woocommerce_order_is_vat_exempt', 'remove_tax_for_exempt', 10, 2);

Resources