I am really stuck and have tried every email hook under the sun. I used an outdated PHP code developed by someone else and revised it for new woocommerce hooks (as the code is 4years old). Everything works perfectly but i need the customer field "billing_vat" to appear in the new order admin email. I will share my code and any help will be greatly appreciated please!!
Thanks
//create vat number billing field
add_filter('woocommerce_billing_fields' , 'display_billing_vat_fields');
function display_billing_vat_fields($billing_fields){
$billing_fields['billing_vat'] = array(
'type' => 'text',
'label' => __('VAT number', 'woocommerce' ),
'class' => array('form-row-wide'),
'required' => false,
'clear' => true,
'priority' => 30, // To change the field location increase or decrease this value
);
return $billing_fields;
}
// Printing the Billing Address on My Account
add_filter( 'woocommerce_my_account_my_address_formatted_address',
'custom_my_account_my_address_formatted_address', 10, 3 );
function custom_my_account_my_address_formatted_address( $fields, $customer_id, $type ) {
if ( $type == 'billing' ) {
$fields['vat'] = get_user_meta( $customer_id, 'billing_vat', true );
}
return $fields;
}
// Checkout -- Order Received (printed after having completed checkout)
add_filter( 'woocommerce_order_formatted_billing_address',
'custom_add_vat_formatted_billing_address', 10, 2 );
function custom_add_vat_formatted_billing_address( $fields, $order ) {
$fields['vat'] = $order->get_meta('billing_vat');
return $fields;
}
// Creating merger VAT variables for printing formatting
add_filter( 'woocommerce_formatted_address_replacements',
'custom_formatted_address_replacements', 10, 2 );
function custom_formatted_address_replacements( $replacements, $args ) {
$replacements['{vat}'] = ! empty($args['vat']) ? $args['vat'] : '';
$replacements['{vat_upper}'] = ! empty($args['vat']) ? strtoupper($args['vat']) : '';
return $replacements;
}
//Defining the Spanish formatting to print the address, including VAT.
add_filter( 'woocommerce_localisation_address_formats', 'custom_localisation_address_format' );
function custom_localisation_address_format( $formats ) {
foreach($formats as $country => $string_address ) {
$formats[$country] = str_replace('{company}\n', '{company}\n{vat_upper}\n', $string_address);
}
return $formats;
}
add_filter( 'woocommerce_customer_meta_fields', 'custom_customer_meta_fields' );
function custom_customer_meta_fields( $fields ) {
$fields['billing']['fields']['billing_vat'] = array(
'label' => __( 'VAT number', 'woocommerce' )
);
return $fields;
}
add_filter( 'woocommerce_admin_billing_fields', 'custom_admin_billing_fields' );
function custom_admin_billing_fields( $fields ) {
$fields['vat'] = array(
'label' => __( 'VAT number', 'woocommerce' ),
'show' => true
);
return $fields;
}
add_filter( 'woocommerce_found_customer_details', 'custom_found_customer_details' );
function custom_found_customer_details( $customer_data ) {
$customer_data['billing_vat'] = get_user_meta( $_POST['user_id'], 'billing_vat', true );
return $customer_data;
}
add_filter('woocommerce_email_order_meta_fields', 'supine_add_email_order_meta_fields', 10, 3 );
function supine_add_email_order_meta_fields( $fields, $sent_to_admin, $order_obj ) {
$billing = get_post_meta( $order_obj->get_order_number(), 'billing_vat', true );
return $fields;
}
Shortly after posting this, i found a fix for it. I had to define the new key "billing_vat" so that it posted with other user information. All the code above is correct except the last add_filter hook. Replace that with the following code, and you have added an optional vat_number field to your checkout, admin backend as well as order emails. Here's the code snippet to replace last "add_filter" hook:
// VAT Number in emails
add_filter( 'woocommerce_email_order_meta_keys',
'supine_vat_number_display_email' );
function supine_vat_number_display_email( $keys ) {
$keys['VAT Number'] = '_billing_vat';
return $keys;
}
code goes in functions.php of your active child theme. Tested and working.
Related
In Wordpress Woocommerce checkout page I want to make field 'billing_name' not required if checkbox 'buy_on_company' is checked.
I have managed to hide 'billing_name' in checkout page, but how to make it not required also?
add_filter( 'woocommerce_checkout_fields' , 'company_checkbox_and_new_checkout_fields', 9999 );
function company_checkbox_and_new_checkout_fields( $fields ) {
$fields['billing']['buy_on_company'] = array( // CSS ID
'type' => 'checkbox',
'label' => __('Buy on company', 'woocommerce'),
'class' => array('form-row-wide'), // CSS Class
//'label_class' => array('woocommerce-form__label woocommerce-form__label-for-checkbox checkbox'),
'clear' => true,
'priority' => '10'
);
$fields['billing']['billing_name']['placeholder'] = 'First Name Last name';
return $fields;
}
function hook_javascript() {
?>
<script>
document.getElementById('buy_on_company').onclick = function () {
if (this.checked) {
document.getElementById('billing_name').style['display'] = 'none';
} else {
document.getElementById('billing_name').style['display'] = 'block';
}
};
</script>
<?php
}
add_action( 'woocommerce_after_checkout_form', 'hook_javascript' );
I have done this:
add_filter( 'woocommerce_checkout_fields' , 'company_checkbox_and_new_checkout_fields_1', 9999 );
function company_checkbox_and_new_checkout_fields_1( $fields ) {
if (isset($_POST['buy_on_company'])) {
$fields['billing']['billing_name']['required'] = false;
} else {
$fields['billing']['billing_name']['required'] = true;
}
return $fields;
}
Now it doesn't ask for billing name field.
Please accept my apology in advance if my question is long.
I am using a payment gateway of woocommerce.
When click on checkout it goes to an external link. Then there We have button to click and Then It goes to another link which make it enable to pay via cards.
Now What I want to do is that.
I want to minimize some step.
1- If possible I want to bypass detail page which appears after click on Checkout button.
2- Is this possible to hide amount on detail page. As my website currecny is different and this payment gateway the show in different.
3- If above 1,2 not possible. Can simply put external pages in a iframe.
So if user click on check out. It should show a ifram on new page current page with redirected link.
Below code is from gateway plugin.
<?php
add_action( 'plugins_loaded', 'init_pp_woo_gateway');
function mib_ppbycp_settings( $links ) {
$settings_link = 'Setup';
array_push( $links, $settings_link );
return $links;
}
$plugin = plugin_basename( __FILE__ );
add_filter( "plugin_action_links_$plugin", 'mib_ppbycp_settings' );
function init_pp_woo_gateway(){
if ( ! class_exists( 'WC_Payment_Gateway' ) ) return;
class WC_Gateway_MIB_PayPro extends WC_Payment_Gateway {
// Logging
public static $log_enabled = false;
public static $log = false;
var $merchant_id;
var $merchant_password;
var $test_mode;
var $plugin_url;
var $timeout;
var $checkout_url;
var $api_url;
var $timeout_in_days;
public function __construct(){
global $woocommerce;
$this -> plugin_url = WP_PLUGIN_URL . DIRECTORY_SEPARATOR . 'woocommerce-paypro-payment';
$this->id = 'mibwoo_pp';
$this->has_fields = false;
$this->checkout_url = 'https://marketplace.paypro.com.pk/';
$this->icon = 'https://thebalmainworld.com/wp-content/uploads/2020/10/Credit-Card-Icons-copy-1.png';
$this->method_title = 'Paypro';
$this->method_description = 'Pay via Debit/Credit card.';
$this->title = "Paypro";
$this->description = "Pay via Debit/Credit card.";
$this->merchant_id = $this->get_option( 'merchant_id' );
$this->merchant_password = trim($this->get_option( 'merchant_password' ));
$this->merchant_secret = $this->get_option( 'merchant_secret' );
$this->test_mode = $this->get_option('test_mode');
$this->timeout_in_days = $this->get_option('timeout_in_days');
$this->debug = $this->get_option('debug');
$this->pay_method = "Paypro";
if($this->timeout_in_days==='yes'){
$this->timeout = trim($this->get_option( 'merchant_timeout_days' ));
}
else{
$this->timeout = trim($this->get_option( 'merchant_timeout_minutes' ));
}
if($this->test_mode==='yes'){
$this->api_url = 'https://demoapi.paypro.com.pk';
}
else{
$this->api_url = 'https://api.paypro.com.pk';
}
$this->init_form_fields();
$this->init_settings();
self::$log_enabled = $this->debug;
// Save options
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
// Payment listener/API hook
add_action( 'woocommerce_api_wc_gateway_mib_paypro', array( $this, 'paypro_response' ) );
}
function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'yes'
),
'merchant_id' => array(
'title' => __( 'Merchant Username', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This Merchant Username Provided by PayPro', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
),
'test_mode' => array(
'title' => __( 'Enable Test Mode', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'yes'
),
'merchant_password' => array(
'title' => __( 'Merchant Password', 'woocommerce' ),
'type' => 'password',
'description' => __( 'Merchant Password Provided by PayPro', 'woocommerce' ),
'default' => __( '', 'woocommerce' ),
'desc_tip' => true,
),
'merchant_secret' => array(
'title' => __( 'Secret Key', 'woocommerce' ),
'type' => 'password',
'description' => __( 'Any Secret Key Or Word with No Spaces', 'woocommerce' ),
'default' => __( rand(), 'woocommerce' ),
'desc_tip' => true,
),
'merchant_timeout_minutes' => array(
'title' => __( 'Timeout (In Minutes)', 'woocommerce' ),
'type' => 'number',
'description' => __( 'Timeout Before order expires it can be between 5 to 30 minutes', 'woocommerce' ),
'default' => __( 5, 'woocommerce' ),
'desc_tip' => true,
'custom_attributes' => array(
'min' => 5,
'max' => 30
)
),
'timeout_in_days' => array(
'title' => __( 'Enable Timeout in days', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'no'
),
'merchant_timeout_days' => array(
'title' => __( 'Timeout (In Days)', 'woocommerce' ),
'type' => 'number',
'description' => __( 'Minimum 1 day Max 3 Days. Remember, It works as due date you\'ve selected 1 day the expiration date of the PayPro id will be set as the day after today.', 'woocommerce' ),
'default' => __( 1, 'woocommerce' ),
'desc_tip' => true,
'custom_attributes' => array(
'min' => 1,
'max' => 3
)
),
'debug' => array(
'title' => __( 'Debug Log', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable logging', 'woocommerce' ),
'default' => 'no',
'description' => sprintf( __( 'Debug Information <em>%s</em>', 'woocommerce' ), wc_get_log_file_path( 'paypro' ) )
),
);
}
/**
* Logging method
* #param string $message
*/
public static function log( $message ) {
if ( self::$log_enabled ) {
if ( empty( self::$log ) ) {
self::$log = new WC_Logger();
}
$message = is_array($message) ? json_encode($message) : $message;
self::$log->add( 'paypro', $message );
}
}
/**
* Process the payment and return the result
*
* #access public
* #param int $order_id
* #return array
*/
function process_payment( $order_id ) {
$order = new WC_Order( $order_id );
$paypro_args = $this->get_paypro_args( $order );
$paypro_args = http_build_query( $paypro_args, '', '&' );
$this->log("========== Payment Processing Started: args =========");
$this->log($paypro_args);
//if demo is enabled
$checkout_url = $this->checkout_url;;
return array(
'result' => 'success',
// 'redirect' => 'http://localhost:8000/secureform?'.$paypro_args
'redirect' => 'https://marketplace.paypro.com.pk/secureform?'.$paypro_args
);
}
/**
* Get PayPro Args for passing to PP
*
* #access public
* #param mixed $order
* #return array
*/
function get_paypro_args( $order ) {
global $woocommerce;
$order_id = $order->get_id();
//Encrypting the username and password
$token1 = $this->merchant_id;
$token2 = $this->merchant_password;
$cipher_method = 'aes-128-ctr';
$secret_word = md5($this->merchant_secret);
$enc_key = openssl_digest($secret_word.date('d/m/y'), 'SHA256', TRUE);
$enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));
$crypted_token1 = openssl_encrypt($token1, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
$crypted_token2 = openssl_encrypt($token2, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
unset($token, $cipher_method, $enc_key, $enc_iv);
// PayPro Args
$paypro_args = array(
'mid' => $crypted_token1,
'mpw' => $crypted_token2,
'secret_public' => base64_encode($this->merchant_secret),
'is_encrypted' => 1,
'mode' => $this->test_mode,
'timeout_in_days' => $this->timeout_in_days,
'merchant_order_id' => $order_id,
'merchant_name' => get_bloginfo( 'name' ),
'request_is_valid' => 'true',
'request_from' => 'woocommerce',
// Billing Address info
'first_name' => $order->get_billing_first_name(),
'last_name' => $order->get_billing_last_name(),
'street_address' => $order->get_billing_address_1(),
'street_address2' => $order->get_billing_address_2(),
'city' => $order->get_billing_city(),
'state' => $order->get_billing_state(),
'zip' => $order->get_billing_postcode(),
'country' => $order->get_billing_country(),
'email' => $order->get_billing_email(),
'phone' => $order->get_billing_phone(),
);
if (!function_exists('is_plugin_active')) {
include_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
if(is_plugin_active( 'custom-order-numbers-for-woocommerce/custom-order-numbers-for-woocommerce.php' )){
$paypro_args['paypro_order_id'] = time().'-'.get_option( 'alg_wc_custom_order_numbers_counter', 1 );
}
else{
$paypro_args['paypro_order_id'] = time().'-'.$order_id;
}
// Shipping
if ($order->needs_shipping_address()) {
$paypro_args['ship_name'] = $order->get_shipping_first_name().' '.$order->get_shipping_last_name();
$paypro_args['company'] = $order->get_shipping_company();
$paypro_args['ship_street_address'] = $order->get_shipping_address_1();
$paypro_args['ship_street_address2'] = $order->get_shipping_address_2();
$paypro_args['ship_city'] = $order->get_shipping_city();
$paypro_args['ship_state'] = $order->get_shipping_state();
$paypro_args['ship_zip'] = $order->get_shipping_postcode();
$paypro_args['ship_country'] = $order->get_shipping_country();
}
$paypro_args['x_receipt_link_url'] = $this->get_return_url( $order );
$paypro_args['request_site_url'] = get_site_url();
$paypro_args['request_site_checkout_url'] = wc_get_checkout_url();
$paypro_args['return_url'] = $order->get_cancel_order_url();
$paypro_args['issueDate'] = date('d/m/Y');
$paypro_args['cartTotal'] = $order->get_total();
$paypro_args['store_currency'] = get_woocommerce_currency();
$paypro_args['store_currency_symbol'] = get_woocommerce_currency_symbol();
//Getting Cart Items
$billDetails= array();
$flag = 0;
foreach ($order->get_items() as $item => $values){
// Get the product name
$product_name = $values['name'];
// Get the item quantity
$item_quantity = $order->get_item_meta($item, '_qty', true);
// Get the item line total
$item_total = $order->get_item_meta($item, '_line_total', true);
$price = $item_total/$item_quantity;
$billDetails[$flag]['LineItem'] = esc_html($product_name);
$billDetails[$flag]['Quantity'] = $item_quantity;
$billDetails[$flag]['UnitPrice'] = $price;
$billDetails[$flag++]['SubTotal'] = $item_total;
}
$paypro_args['cartItemList'] = urlencode(json_encode($billDetails));
////
//setting payment method
if ($this->pay_method)
$paypro_args['pay_method'] = $this->pay_method;
//if test_mode is enabled
if ($this -> test_mode == 'yes'){
$paypro_args['test_mode'] = 'Y';
}
//if timeout_in_days is enabled
if ($this -> timeout_in_days == 'yes'){
$paypro_args['timeout'] = $this->timeout;
}
else{
$paypro_args['timeout'] = $this->timeout*60;
}
$paypro_args = apply_filters( 'woocommerce_paypro_args', $paypro_args );
return $paypro_args;
}
/**
* this function is return product object for two
* different version of WC
*/
function get_product_object(){
return $product;
}
/**
* Check for PayPro IPN Response
*
* #access public
* #return void
*/
function paypro_response() {
global $woocommerce;
// woocommerce_log($_REQUEST);
$this->log(__("== INS Response Received == ", "PayPro") );
$this->log( $_REQUEST );
$wc_order_id = '';
if( !isset($_REQUEST['merchant_order_id']) ) {
if( !isset($_REQUEST['vendor_order_id']) ) {
$this->log( '===== NO ORDER NUMBER FOUND =====' );
exit;
} else {
$wc_order_id = $_REQUEST['vendor_order_id'];
}
} else {
$wc_order_id = $_REQUEST['merchant_order_id'];
}
$this->log(" ==== ORDER -> {$wc_order_id} ====");
// echo $wc_order_id;
$wc_order_id = apply_filters('woocommerce_order_no_received', $wc_order_id, $_REQUEST);
$this->log( "Order Received ==> {$wc_order_id}" );
// exit;
$wc_order = new WC_Order( absint( $wc_order_id ) );
$this->log("Order ID {$wc_order_id}");
$this->log("WC API ==> ".$_GET['wc-api']);
// If redirect after payment
if( isset($_GET['key']) && (isset($_GET['wc-api']) && strtolower($_GET['wc-api']) == 'wc_gateway_mib_paypro') ) {
$this->verify_order_by_hash($wc_order_id);
exit;
}
$message_type = isset($_REQUEST['message_type']) ? $_REQUEST['message_type'] : '';
$sale_id = isset($_REQUEST['sale_id']) ? $_REQUEST['sale_id'] : '';
$invoice_id = isset($_REQUEST['invoice_id']) ? $_REQUEST['invoice_id'] : '';
$fraud_status = isset($_REQUEST['fraud_status']) ? $_REQUEST['fraud_status'] : '';
$this->log( "Message Type/Fraud Status: {$message_type}/{$fraud_status}" );
switch( $message_type ) {
case 'ORDER_CREATED':
$wc_order->add_order_note( sprintf(__('ORDER_CREATED with Sale ID: %d', 'woocommerce'), $sale_id) );
$this->log(sprintf(__('ORDER_CREATED with Sale ID: %d', 'woocommerce'), $sale_id));
break;
case 'FRAUD_STATUS_CHANGED':
if( $fraud_status == 'pass' ) {
// Mark order complete
$wc_order->payment_complete();
$wc_order->add_order_note( sprintf(__('Payment Status Clear with Invoice ID: %d', 'woocommerce'), $invoice_id) );
$this->log(sprintf(__('Payment Status Clear with Invoice ID: %d', 'woocommerce'), $invoice_id));
add_action('woocommerce_order_completed', $order, $sale_id, $invoice_id);
} elseif( $fraud_status == 'fail' ) {
$wc_order->update_status('failed');
$wc_order->add_order_note( __("Payment Declined", 'woocommerce') );
$this->log( __("Payment Declined", 'woocommerce') );
}
break;
}
exit;
}
function verify_order_by_hash($wc_order_id) {
global $woocommerce;
#ob_clean();
$paypro_id = $_REQUEST['paypro_id'];
$tpaycode = $_REQUEST['tpaycode'];
$order_id = $_REQUEST['merchant_order_id'];
$wc_order = wc_get_order( $wc_order_id );
// $order_total = isset($_REQUEST['total']) ? $_REQUEST['total'] : '';
$order_total = $wc_order->get_total();
$compare_string = $this->merchant_id . $paypro_id . $order_total;
$compare_hash1 = strtoupper(md5($compare_string));
$this->log("Compare String ===>" .$compare_string);
$compare_hash2 = $_REQUEST['key'];
if ($compare_hash1 != $compare_hash2) {
$this->log("Hash_1 ==> {$compare_hash1}");
$this->log("Hash_2 ==> {$compare_hash2}");
wp_die( "PayPro Hash Mismatch... check your secret word." );
} else {
//Curl Request
$url = $this->api_url.'/cpay/gos?userName=' . $this->merchant_id . '&password=' . $this->merchant_password . '&cpayId=' . $tpaycode;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
// Submit the GET request
$result = curl_exec($ch);
if (curl_errno($ch)) //catch if curl error exists and show it
echo 'Curl error: ' . curl_error($ch);
else {
//Check if the order ID passed is the same or fake
$res = json_decode($result, true);
$returnedOrderID = explode('-',$res[1]['OrderNumber']);
if ($returnedOrderID[1]===$order_id) {
if (strtoupper($res[1]['OrderStatus']) == "PAID") {
$wc_order->add_order_note( sprintf(__('Payment completed via PayPro Order Number %d', 'paypro'), $tpaycode) );
// Mark order complete
$wc_order->payment_complete();
// Empty cart and clear session
$woocommerce->cart->empty_cart();
$order_redirect = add_query_arg('paypro','processed', $this->get_return_url( $wc_order ));
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
} elseif (strtoupper($res[1]['OrderStatus']) == "BLOCKED") {
$wc_order->add_order_note( sprintf(__('Error processing the payment of Order Number %d', 'paypro'), $tpaycode) );
$order_redirect = add_query_arg('paypro','canceled', $wc_order->get_cancel_order_url());
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
}
elseif (strtoupper($res[1]['OrderStatus']) == "UNPAID") {
$wc_order->add_order_note( sprintf(__('Error processing the payment of Order Number %d', 'paypro'), $tpaycode) );
$order_redirect = add_query_arg('paypro','pending', $wc_order->get_cancel_order_url());
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
}
}
}
}
}
function get_price($price){
$price = wc_format_decimal($price, 2);
return apply_filters('mib_get_price', $price);
}
}
}
function add_mib_payment_gateway( $methods ) {
$methods[] = 'WC_Gateway_MIB_PayPro';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_mib_payment_gateway' );
function payproco_log( $log ) {
if ( true === WP_DEBUG ) {
if ( is_array( $log ) || is_object( $log ) ) {
$resp = error_log( print_r( $log, true ), 3, plugin_dir_path(__FILE__).'payproco.log' );
} else {
$resp = error_log( $log, 3, plugin_dir_path(__FILE__).'payproco.log' );
}
var_dump($resp);
}
}
I am trying to connect to an api using the code below, so when the customer clicks on the "place order" button on the Woocommerce checkout page, I am getting a "please try again" error:
var amount = <?php global $woocommerce; print WC()->cart->total; ?>;
var merchantOrderId = '<?php echo print time(); ?>';
var apiKey = 'm85BXXLpf_icrSvqbElR11xquEgmKZ8wfeRb2ly3-G7pIwCKDuytgplB7AQGi-5t';
renderMMoneyPaymentButton(amount, merchantOrderId, apiKey);
I am trying to pass this information to the api via this function but I am not getting a successful connection.
public function process_payment( $order_id ) {
global $woocommerce;
// we need it to get any order detailes
$order = new WC_Order($order_id);
/*
* Array with parameters for API interaction
*/
$args = array(
'amount' => '<?php global $woocommerce; print WC()->cart->total; ?>',
'merchant_order_id' => '<?php print time(); ?>',
'api_Key' => 'm85BXXLpf_icrSvqbElR11xquEgmKZ8wfeRb2ly3-G7pIwCKDuytgplB7AQGi-5t',
'currency' => 'BBD',
);
/*
* Your API interaction could be built with wp_remote_post()
*/
$response = wp_remote_post( 'https://api.mmoneybb.com/merchant/js/mmoney-payment.js', $args );
if( !is_wp_error( $response ) ) {
$body = json_decode( $response['body'], true );
// it could be different depending on your payment processor
if ( $body ['$response'] == 'APPROVED') {
// we received the payment
$order->payment_complete();
$order->reduce_order_stock();
// some notes to customer (replace true with false to make it private)
$order->add_order_note( 'Thanks for your payment!!!!', true );
// Empty cart
$woocommerce->cart->empty_cart();
// Redirect to the thank you page
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
} else {
wc_add_notice( 'Please try again.', 'error' );
return;
}
} else {
wc_add_notice( 'Connection error.', 'error' );
return;
}
}
let me know what i am doing wrong much appreciated also this is the other script as well
function renderMMoneyPaymentButton(amount, merchantOrderId, apiKey) {
let paymentParams = {
amount: amount,
api_key: apiKey,
currency: 'BBD',
merchant_order_id: merchantOrderId,
onCancel: function () { console.log('Modal closed'); },
onError: function(error) { console.log('Error', error); },
onPaid: function (invoice) { console.log('Payment complete', invoice); }
};
// "mMoney" window global provided by sourcing mmoney-payment.js script.
// Attach the button to the empty element.
mMoney.payment.button.render(paymentParams, '#mmoney-payment-button');
}
1) In your first snippet code you are using javascript and you need to get the order Id and then the order total… You can only get the Order ID after the order is placed…
There is an answer example here.
2) Your 2nd public function involves only PHP… There are some errors and mistakes in this code. Try the following revisited code instead:
public function process_payment( $order_id ) {
// Get The WC_Order Object instance
$order = wc_get_order( $order_id );
/*
* Array with parameters for API interaction
*/
$args = array(
'amount' => $order->get_total(),
'merchant_order_id' => $order_id,
'api_Key' => 'm85BXXLpf_icrSvqbElR11xquEgmKZ8wfeRb2ly3-G7pIwCKDuytgplB7AQGi-5t',
'currency' => $order->get_currency(),
);
/*
* Your API interaction could be built with wp_remote_post()
*/
$response = wp_remote_post( 'https://api.mmoneybb.com/merchant/js/mmoney-payment.js', $args );
if( !is_wp_error( $response ) ) {
$body = json_decode( $response['body'], true );
// it could be different depending on your payment processor
if ( $body ['$response'] == 'APPROVED') {
// we received the payment
$order->payment_complete();
$order->reduce_order_stock();
// some notes to customer (replace true with false to make it private)
$order->add_order_note( 'Thanks for your payment!!!!', true );
// Empty cart
$woocommerce->cart->empty_cart();
// Redirect to the thank you page
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
} else {
wc_add_notice( 'Please try again.', 'error' );
return;
}
} else {
wc_add_notice( 'Connection error.', 'error' );
return;
}
}
It should better work.
I am currently using the Wordpress REST API to read and write posts.
I have created a custom post type called property:
register_post_type( 'property', array(
'labels' => array(
'name' => 'Properties',
'singular_name' => 'Property',
),
'description' => '',
'show_in_rest' => true,
'public' => true,
'menu_position' => 20,
'supports' => array( 'title', 'editor')
));
add_action( 'init', 'property_cpt' );
And I have added a custom metabox called property_name so the it will appear in the edit post admin page:
function add_property_metaboxes(){
add_meta_box(
'property_name', // id
'Name', // title
'property_name_callback', // callback
'property', // page
'normal', // context
'default' // priority
);
}
function property_name_callback() {
global $post;
wp_nonce_field( basename( __FILE__ ), 'property_fields' );
$value = get_post_meta( $post->ID, 'property_name', true );
echo '<input name="property_name" type="text" value="' . $value . '" />';
}
add_action( 'add_meta_boxes', 'add_property_metaboxes' );
I am handling the save function for this post type:
function property_save_meta( $post_id, $post ) {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
if ( !isset( $_POST['property_name'] ) ||
!wp_verify_nonce( $_POST['property_fields'], basename(__FILE__) ) ) {
return $post_id;
}
$events_meta['property_name'] = esc_textarea( $_POST['property_name'] );
foreach ( $events_meta as $key => $value ) :
if ( 'revision' === $post->post_type ) {
return;
}
if ( get_post_meta( $post_id, $key, false ) ) {
update_post_meta( $post_id, $key, $value );
} else {
add_post_meta( $post_id, $key, $value);
}
if ( ! $value ) {
delete_post_meta( $post_id, $key );
}
endforeach;
}
add_action( 'save_post', 'property_save_meta', 1, 2 );
And finally I have registered property_name as a rest field:
function register_rest_fields() {
register_rest_field('property', 'property_name',
array(
'get_callback' => 'get_post_meta_cb',
'update_callback' => 'update_post_meta_cb',
'schema' => null
)
);
}
function get_post_meta_cb($object, $field_name, $request){
return get_post_meta($object['id'], $field_name, true);
}
function update_post_meta_cb($value, $object, $field_name){
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_term_meta( $object->ID, $field_name, $value );
}
add_action('rest_api_init', 'register_rest_fields');
On the front-end, I am able to fetch 'property' posts using the API and the property_name field appears correctly in the response.
I am also able to create a new post easily but I am not able to set the property_name meta field value.
Currently I am trying:
request(`${url}/wp-json/wp/v2/property`, {
method: "POST",
body:JSON.stringify({
title: 'Lorem ipsum dolor sit amet',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
status: 'publish',
meta: {
property_name: 'Testing'
}
})
});
(As pointed in my comment,) the problem is here:
function update_post_meta_cb($value, $object, $field_name){
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_term_meta( $object->ID, $field_name, $value );
}
where you're actually saving a post meta, but then used update_term_meta() which is for saving a term meta. :)
And (I forgot to say that) to fix it, just replace the update_term_meta() with update_post_meta(). ;)
I'm using jQueryUI AutoComplete with WordPress to fetch terms of a custom taxonomy as a user types in a search box.
I have a lot of sports brands as custom taxonomy terms, so, for example, the term Adidas can have many subterms. Now when I type a, it displays...
Adidas
Adidas Shoes
Adidas Socks
etc...
...causing the other brands to get in the dark. So, when I type a, I would like the results to show as follows...
Adidas
Amphipod
Asics
etc...
...until I continue typing ad, and only then should the Adidas results with the subterms appear, like in the first example. Is this possible to accomplish? Is jQueryUI AutoComplete able to order the results for me like this, or do I need to sort them on the server side with a PHP function like sort, usort etc.? I've tried to write a few different PHP sort functions to no avail so far, but I really have no idea right now.
This is the code I have right now:
autocomplete.js
$(function() {
var url = MyAutocomplete.url + "?action=my_search";
$('.search-field').autocomplete({
source: url,
delay: 500,
minLength: 2,
sortResults: true
})
});
functions.php (WordPress)
function my_search()
{
$args = array(
'search' => strtolower($_GET['term']),
'taxonomy' => array('suggestion_string'),
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
'number' => 10,
);
$search_query = new WP_Term_Query($args);
$results = array( );
if ( $search_query->get_terms() ) {
foreach($search_query->get_terms() as $term) {
$results[] = array(
'label' => $term->name,
);
}
}
else {
}
// Tried to write a few different sort functions here to no avail, like:
sort($results);
$data = json_encode($results);
echo html_entity_decode( $data );
exit();
}
add_action( 'wp_ajax_my_search', 'my_search' );
add_action( 'wp_ajax_nopriv_my_search', 'my_search' );
Everything is possible my friend you just have to code it as you wish. You can achieve what you want on the server side as well as on the client side, in this case I would recommend the server side though.
If you do not want autocomplete show subcategories just do not deliver those. Either you eliminate names starting with the same word first or you exclude subcategories. Here is my code for you for the first possibility:
function my_search()
{
$args = array(
'search' => strtolower($_GET['term']),
'taxonomy' => array('suggestion_string'),
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
'number' => 10,
);
$search_query = new WP_Term_Query($args);
$results = array( );
if ( $search_query->get_terms() ) {
foreach($search_query->get_terms() as $term) {
$results[] = array(
'label' => $term->name,
);
}
}
else {
}
$filtered = [];
$existing = [];
if(strlen($_GET['term'])<2) {
foreach($results as $term) {
$first_word = explode(" ",$term["label"])[0];
if(!in_array($first_word,$existing) {
array_push($existing,$first_word);
$filtered[] = $term;
}
}
} else {
$filtered = $results;
}
$data = json_encode($results);
echo html_entity_decode( $data );
exit();
}
add_action( 'wp_ajax_my_search', 'my_search' );
add_action( 'wp_ajax_nopriv_my_search', 'my_search' );