Custom WooCommerce Gateway - wordpress

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,
);

Related

How speed up the woocommerce REST API in sync product stock quantity?

I want sync stock quantity of site B (remote site) with site A, ie. when an order in site A is in process status, the quantity of same product in site B will be updated.
For mapping product IDs, I add post meta in both site A and B.
In order to do so, I use following codes. It works, but my problem is speed process when stock quantity wants to be updated in site B, it takes more seconds.
add_action('woocommerce_order_status_changed', 'update_base_site_inventory',11, 1);
function update_base_site_inventory($order_id){
$order = wc_get_order( $order_id );
if ($order->status == 'processing') {
$items = $order->get_items();
foreach($items as $item){
$product = wc_get_product($item->get_product_id());
$product_quantity = $product->get_stock_quantity();
$id_mapped = get_post_meta($item->get_product_id(), 'map_product_id', true);
$batch_update['update'] = array(array('id' => current($id_mapped), 'stock_quantity' => $product_quantity));
}
$api_response = wp_remote_request(
'https://...../wp-json/wc/v3/products/batch/', array(
'method' => 'POST',
'headers' => array('Authorization' => 'Basic ' . base64_encode( '....:.....' )),
'body' => $batch_update
)
);
}
}
is my approach correct? what should I do? is there any way to increase the API request speed?
Thanks,
Try using WooCommerce Client Library, install using composer:
composer require automattic/woocommerce
Then use it in your code like this:
add_action('woocommerce_order_status_changed', 'update_base_site_inventory', 11, 1);
function update_base_site_inventory($order_id)
{
$order = wc_get_order($order_id);
if ($order->status == 'processing') {
$data = array();
$items = $order->get_items();
foreach ($items as $item) {
$product = wc_get_product($item->get_product_id());
$product_quantity = $product->get_stock_quantity();
$id_mapped = get_post_meta($item->get_product_id(), 'map_product_id', true);
$data[] = array(
'id' => current($id_mapped),
'stock_quantity' => $product_quantity
);
}
// Include the library
require __DIR__ . '/vendor/autoload.php';
// Initialize the library
$woocommerce = new Automattic\WooCommerce\Client(
'https://example.com', // Your store URL
'ck_....................', // Your consumer key
'cs_....................', // Your consumer secret
[
'wp_api' => true, // Enable the WP REST API integration
'version' => 'wc/v3', // WooCommerce WP REST API version
'verify_ssl' => false
]
);
// Make the update
$woocommerce->post('products/batch', array(
'update' => array($data),
));
}
}

How to submit contact form 7 programmatically

I want to submit contact form by custom function
The code below is getting the instance of form but when submitted. It submit the form but not the fields which I wanted.
$item = wpcf7_contact_form( $formId );
$result = $item->submit();
Here where I can pass the fields I define in admin panel like "textarea-123" & "email-234" ?
I did not get exact answer for what I look but I found the alternate solution.
function cf7Submit($formId , $args) {
$url = 'http://example.com/wp-json/contact-form-7/v1/contact-forms/'.$formId.'/feedback';
$response = wp_remote_post( $url, array(
'method' => 'POST',
'body' => $args
)
);
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "Something went wrong: $error_message";
} else {
echo 'Response:<pre>';
print_r( $response );
echo '</pre>';
}
}
I can call this function like this:
cf7Submit(128, array(
'textarea-123' => 'test email',
'email-234' => 'asd#asd.com'));
#daraptoor has found a good solution, but as #davevsdave noticed in the comment, it does not work properly in CF7 5.6.
Error 415 is caused by added to API check for content type passed into a request header:
// part of create_feedback() from CF7's rest-api.php
if ( ! str_starts_with( $content_type, 'multipart/form-data' ) ) {
To figure it out, just add the expected content type into a request header:
$response = wp_remote_post( $url, array(
'method' => 'POST',
'headers' => array(
'Content-Type' => 'multipart/form-data'
),
'body' => $args
)
);
UPD
Faced with an issue, that wp_remote_post() send data in body and not in POST, so CF7 API does not get any fields. It is caused because the WP's function uses http_build_query() (read more here).
I have used cURL request as a workaround:
// Same user agent as in regular wp_remote_post().
$userAgent = 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url');
// Note that Content-Type wrote in a bit different way.
$header = ['Content-Type: multipart/form-data'];
// Same array with fields to pass, not changed.
$body = ['foo' => 'bar'];
$curlOpts = [
// Send as POST
CURLOPT_POST => 1,
// Get a response data instead of true
CURLOPT_RETURNTRANSFER => 1,
// CF7 will reject your request as spam without it.
CURLOPT_USERAGENT => $userAgent,
CURLOPT_HTTPHEADER => $header,
CURLOPT_POSTFIELDS => $body,
];
$ch = curl_init($apiUrl); // Create a new cURL resource.
curl_setopt_array($ch, $curlOpts); // Set options.
$response = curl_exec($ch); // Grab response.
if (!$response) {
// Do something if an error occurred.
} else {
$response = json_decode($response);
// Do something with the response data.
}
// Close cURL resource, and free up system resources.
curl_close($ch);
Hope it saves someones time :)
You can add a piece of JS code, like:
$("form.wpcf7").submit()

Why wp_update_post return invalid post id

I am getting an error with WordPress wp_update_post() function that says "Invalid post ID". Here is my code:
$current_item = 273;
$my_post = array(
'ID' => $current_item,
'post_title' => 'This is the post title.',
'post_content' => 'This is the updated content.',
);
$post_id = wp_update_post( $my_post, true );
if (is_wp_error($post_id)) {
$errors = $post_id->get_error_messages();
foreach ($errors as $error) {
echo $error;
}
}
Thanks in advance .
Use 'import_id', not 'ID'.
If there is no post at the ID you specify, wp_update_post() doesn't create a new one - it returns an error. In order to specify the ID of a new post use 'import_id' => $current_item.
Note, though, that if there IS a post with that ID, import_id will cause a new post instead of an update. So if you want to EITHER make a new post with that ID OR update the post at that ID, you'll need an if statement to pick your key:
$newPostKey = (get_post_status($current_item)) ? 'ID' : 'import_id';
// If there's a post with an ID of $current_item, we'll use 'ID'.
// Otherwise, use 'import_id'.
Here's your shiny new code.
$current_item = 273;
$newPostKey = (get_post_status($current_item)) ? 'ID' : 'import_id';
$my_post = array(
$newPostKey => $current_item,
'post_title' => 'This is the post title.',
'post_content' => 'This is the updated content.',
);
$post_id = wp_update_post( $my_post, true );

Why it gives an error after click on place order button on check out page?

This is my code at checkout page. I was developed custom payment gateway plugin for it, but when i am try to click on place order button it is not submitting the request parameters and not getting response ?
public function process_payment( $order_id ) {
global $woocommerce;
// Get this Order's information so that we know
// who to charge and how much
$customer_order = new WC_Order( $order_id );
// Are we testing right now or is it a real transaction
$Mode = ( $this->Mode == "yes" ) ? 'TRUE' : 'FALSE';
// Decide which URL to post to
$environment_url = ( "FALSE" == $Mode )
? 'https://www.qpayindia.com/wwws/Payment/PaymentDetails.aspx'
: 'https://www.qpayindia.com/wwws/Payment/PaymentDetails.aspx';
// This is where the fun stuff begins
$payload = array(
// Authorize.net Credentials and API Info
"QPayID" => $this->QPayID,
"QPayPWD" => $this->QPayPWD,
"CaseNumber" => $this->CaseNumber,
"Mode" => $this->Mode,
"Currency" => $this->Currency,
"Amount" => $customer_order->order_total,
"ResponseURL" => $customer_order->get_checkout_payment_url(),
"OrderID" => str_replace( "#", "", $customer_order->get_order_number() ),
// Some Customer Information
"x_cust_id" => $customer_order->user_id,
"x_customer_ip" => $_SERVER['REMOTE_ADDR'],*/
);
// Send this payload to Authorize.net for processing
$response = wp_remote_post( $environment_url, array(
'method' => 'POST',
'body' => http_build_query( $payload ),
'timeout' => 90,
'sslverify' => false,
) );
if ( is_wp_error( $response ) )
throw new Exception( __( 'We are currently experiencing problems trying to connect to this payment gateway. Sorry for the inconvenience.', 'spyr-authorizenet-aim' ) );
if ( empty( $response['body'] ) )
throw new Exception( __( 'Authorize.net\'s Response was empty.', 'spyr-authorizenet-aim' ) );
// Retrieve the body's resopnse if no errors found
$response_body = wp_remote_retrieve_body( $response );
// Parse the response into something we can read
foreach ( preg_split( "/\r?\n/", $response_body ) as $line ) {
$resp = explode( "|", $line );
}
// Get the values we need
$r['ResponseCode'] = $resp[0];
$r['response_sub_code'] = $resp[1];
$r['response_reason_code'] = $resp[2];
$r['Message'] = $resp[3];
// Test the code to know if the transaction went through or not.
// 1 or 4 means the transaction was a success
if ( ( $r['ResponseCode'] == 100 ) || ( $r['ResponseCode'] == 200 ) ) {
// Payment has been successful
$customer_order->add_order_note( __( 'Qpay payment completed.', 'spyr-authorizenet-aim' ) );
// Mark order as Paid
$customer_order->payment_complete();
// Empty the cart (Very important step)
$woocommerce->cart->empty_cart();
// Redirect to thank you page
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $customer_order ),
);
} else {
// Transaction was not succesful
// Add notice to the cart
wc_add_notice( $r['Message'], 'error' );
// Add note to the order for your reference
$customer_order->add_order_note( 'Error: '. $r['Message'] );
}
}

wordpress custom post types - broken publish button

I created a gallery post type (as part of a plugin) that contains besides a title and some meta information also a wp_list_table that queries those attachments which have the current post as post_parent. I ran into a problem when suddenly my publish button stopped working. No matter if I'm creating a new gallery or if I'm editing an old one, once I click on update/publish my changes get lost and I end up on edit.php.
Anybody knows what that's all about?
I where able to figure out where the problem seems to be. It's in my list_table class which inherits from wp_list_table. after commenting out some unimportant functions i ended up with a different error but still no new or updated gallery. Now I get the are you sure you want to do this page.
Even the most basic class won't work...
if( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class Yard_Attachment_Table extends WP_List_Table {
function __construct() {
global $status, $page;
parent::__construct( array(
'singular' => 'yard Attachment',
'plural' => 'yard Attachments',
'ajax' => false
) );
}
function column_default($item, $column_name) {
return 'default';
}
function get_columns(){
$columns = array(
'checkbox' => '<input type="checkbox" />', //for simplicity its not 'cb'
'thumb' => 'Thumbnail',
'title' => 'Titel',
'pos' => 'Position'
);
return $columns;
}
function prepare_items() {
global $wpdb;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
if (isset($_REQUEST['post'])) {
$query = " SELECT *
FROM $wpdb->posts
WHERE post_type = 'attachment'
AND post_parent = {$_REQUEST['post']}";
$data = $wpdb->get_results($query, ARRAY_A);
} else {
$data = array();
}
$this->items = $data;
}
}
In the plugin class' constructor I use
add_action('add_meta_boxes_yard_gallery', array($this, 'yard_metaboxes'));.
In yard_metaboxes I use add_meta_box and in the function I have as a callback i'm creating a new instance of my table class and I call prepare_items() and display()
Turning error_reporting on my page dies with these messages:
Strict Standards: Only variables should be passed by reference in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php on line 210
Warning: Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php:210) in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pluggable.php on line 876
BTW I'm not localizing.
Please help! If i had more reputation I'd offer it.
Adding the meta box code
in my plugin file:
require_once( plugin_dir_path( __FILE__ ) . 'class-yard.php' );
Yard::get_instance();
in my class-yard file the meta box methods are at the bottom:
class Yard {
protected static $instance = null;
private function __construct() {
include_once('class-yard-attachments.php');
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles' ) );
add_action('after_setup_theme', array($this, 'yard_thumbnails'));
add_action('init', array($this, 'yard_post_type'));
add_action('init', array($this, 'yard_taxonomies'));
add_filter('manage_yard_gallery_posts_columns', array($this, 'yard_add_columns'));
add_action('manage_posts_custom_column', array($this, 'yard_fill_columns'));
add_action('add_meta_boxes_yard_gallery', array($this, 'yard_metaboxes'));
}
public static function get_instance() {// If the single instance hasn't been set, set it now.
if (null == self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
public function enqueue_admin_styles() {
$screen = get_current_screen();
if ($screen->post_type == 'yard_gallery') {
wp_register_style( 'yard-gallery-style', plugins_url('css/yard-gallery-style.css', __FILE__) );
wp_enqueue_style( 'yard-gallery-style' );
}
}
public function yard_thumbnails() {
//add_image_size('yard-thumbnail', 100, 100, true);
}
public function yard_post_type() {
$gallery_labels = array(
'name' => 'Galerien',
'singular_name' => 'Galerie',
'all_items' => 'Alle Galerien',
'add_new' => 'Erstellen',
'add_new_item' => 'Neue Galerie erstellen',
'edit_item' => 'Galerie bearbeiten',
'new_item' => 'Neue Galerie',
'view' => 'Galerie anzeigen',
'view_item' => 'Gallerie anzeigen',
'search_items' => 'Galerie durchsuchen',
'not_found' => 'Keine Galerien gefunden',
'not_found_in_trash' => 'Es befinden sich keine Galerien im Papierkorb',
'parent_item_colon' => ''
);
$gallery_args = array(
'labels' => $gallery_labels,
'public' => true,
// 'publicly_queryable' => true,
// 'show_ui' => true,
// 'show_in_menu' => true,
// 'query_var' => true,
'rewrite' => true,
// 'capability_type' => 'post',
// 'hierarchical' => false,
'menu_position' => 12,
'supports' => array(
'title'
)
// 'menu_icon' => plugin_dir_url(__FILE__) . '/assets/icon_16_grey.png'//16x16 png if you want an icon
);
register_post_type('yard_gallery', $gallery_args);
}
public function yard_taxonomies() {
register_taxonomy(
'yard_work_type',
'yard_gallery',
array(
'hierarchical' => true,
'label' => 'Art der Arbeit'
)
);
register_taxonomy(
'yard_subject',
'yard_gallery',
array(
'hierarchical' => true,
'label' => 'Motiv'
)
);
}
public function yard_add_columns( $columns ){
$columns = array(
'cb' => '<input type="checkbox">',
'yard_post_thumb' => 'Thumbnail',
'title' => 'Bezeichnung',
'yard_pos' => 'Position',
'date' => 'Datum'
);
return $columns;
}
public function yard_fill_columns( $column ) {
global $post;
switch ($column) {
case 'yard_post_thumb' :
echo the_post_thumbnail('admin-list-thumb');
break;
}
}
public function yard_metaboxes( $post ) {
global $wp_meta_boxes;
add_meta_box(
'yard-attachments',
'Bilder',
array($this, 'get_yard_attachment_table'),
'yard_gallery'
);
}
public function get_yard_attachment_table() {
$yard_list_table = new Yard_Attachment_Table();
$yard_list_table->prepare_items();
$yard_list_table->display();
}
}
Strict Standards: Only variables should be passed by reference in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php on line 210
The error message tells it all. The ".../popo/mo.php" file has to do with (is related to) the Wordpress translation. (I bet you're using Wordpress with German language files).
I can't see what could be wrong in the code you've posted here, but something is interfering with translation. Looking at what the error message tells us, some variable that Wordpress tries to translate fails to be translated since it's not the correct type.
Warning: Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php:210) in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pluggable.php on line 876
This is a logic result of the previous error message and the headers Wordpress tries to send to the browser.
What's happening: the first error message is being pushed to the client and flushed to the browser screen. Next, Wordpress tries to send it's usual headers and produces an error while doing so because headers have to be send before ANY content is being send to the client.
In other words: the "Cannot modify header information" error always comes up when you echo something to screen and then try to send "header(...)" information. In this case, the translation problem produces the first error message and then Wordpress tries to send headers, which fails and produces the second error message.
TIPS
Check everything you're doing which is related to translation (read: wherever you are passing "German" and/or "English" language strings)
and even more important
Make sure that you're actually passing the correct type(s)... looking at the error and your code, it could well be you're passing a class, a class reference, or another object somewhere instead of the expected variable.

Resources