order_number vs order_id in sofort payment gateway plugin modification
-
Hi,
im using the woocommerce SOFORT gateway plugin.
I’ve been in contact with them because whatever setting I use in their plugin to return the order_number instead of the order_id, I always get the order_id, never the order_number, beeing told that the sequential order plugin can change the behaviour.
These are the two variable settings in their plugin to use for transaction_reason 1 and 2 which are displayed during the sofort ceckout and on the bank statement:
{{order_number}} or {{order_id}}
I always get the order_id but never the order_number in both cases.As your stated on the plugin page “how to make my payment gateway plugin compatible with the sequential order plugin” I found woogate-core.php in my test system and tried to figure out at which place I’d need to replace
$order->get_id()
with
$order->get_order_number()
There are 30 occurrences for $order->get_id() and I could not figure out which of them has to be replaced and which are not.
Of course I’d prefere to get this done by a function/filter (woogate_sofort_transaction_reason_) in my functions.php child theme but I could not yet figure out how I’d accomplish this (I’m not a developer).
So in short: I need the order_number as the sequential order number plugin creates it for and not the post_id of the order.
Thank you for a hint
TomContent of woogate-core.php:
<?php /** * Sofort.com Gateway * * @package WordPress * @subpackage Woocommmerce * @author woo * @copyright 2017 * @link https://woocommerce.com * @license https://www.opensource.org/licenses/gpl-2.0.php GPL License * * Copyright 2021 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // No direct access is allowed if ( ! defined( 'ABSPATH' ) ) { exit; } use Sofort\SofortLib\Sofortueberweisung; use Sofort\SofortLib\Notification; use Sofort\SofortLib\TransactionData; use Sofort\SofortLib\Refund; if ( ! class_exists( 'WooCommerce_Sofortueberweisung' ) ) { /** * Handles the actual gateway (Sofort Banking) * * Adds admin options, frontend fields * and handles payment processing * * @since 1.0.0 */ class WooCommerce_Sofortueberweisung extends WC_Payment_Gateway { /** * Debug modus yes/no * * @since 1.2.0 * * @var string */ public $debug; /** * Logger * * @since 1.2.0 * * @var WC_Logger */ private $logger; /** * Callback URL for notifications * * @since 1.2.0 * * @var string */ private $callback; /** * Payment title which will be shown for customers * * @since 1.2.0 * * @var string */ public $title; /** * Payment description which will be shown for customers * * @since 1.2.0 * * @var string */ public $description; /** * Sofort configkey * * @since 1.2.0 * * @var string */ private $configkey; /** * Sofort transaction reason line 1 * * @since 1.2.0 * * @var string */ private $transaction_reason_1; /** * Sofort transaction reason line 2 * * @since 1.2.0 * * @var string */ private $transaction_reason_2; /** * Sofort notify email address * * @since 1.2.0 * * @var string */ private $notify_email; /** * Sofort notify email address * * @var string * * @since 1.2.0 */ private $trust_pending; /** * Initialize the Gateway * * @since 1.0.0 */ public function __construct() { $this->id = 'sofortgateway'; $this->icon = apply_filters( 'woogate_sofortgateway_icon', $this->get_icon_url() ); $this->has_fields = false; $this->callback = add_query_arg( 'wc-api', 'WooCommerce_Sofortueberweisung', home_url( '/' ) ); $this->supports = array( 'refunds' ); // Load the form fields. $this->init_form_fields(); // Load the settings. $this->init_settings(); $this->title = $this->settings['title']; $this->description = $this->settings['description']; $this->method_title = __( 'Online Bank Transfer.', 'woogate' ); $this->method_description = __( 'Direct payment via online banking. Easy, quick and secure – without registration. Automatic data transfer and the real-time transaction notification enable a smooth payment process and a faster delivery.', 'woogate' ); $this->configkey = $this->settings['configkey']; if ( array_key_exists( 'transaction_reason_1', $this->settings ) ) { $this->transaction_reason_1 = $this->settings['transaction_reason_1']; } else { $this->transaction_reason_1 = $this->form_fields['transaction_reason_1']['default']; } if ( array_key_exists( 'transaction_reason_2', $this->settings ) ) { $this->transaction_reason_2 = $this->settings['transaction_reason_2']; } else { $this->transaction_reason_2 = $this->form_fields['transaction_reason_2']['default']; } $this->trust_pending = $this->settings['trust_pending']; $this->debug = $this->settings['debug']; // Payment listener/API hook add_action( 'woocommerce_api_' . strtolower( get_class( $this ) ), array( &$this, 'payment_listener' ) ); /* 1.6.6 */ add_action( 'woocommerce_update_options_payment_gateways', array( &$this, 'process_admin_options' ) ); /* 2.0.0 */ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Returning icon URL from Klarna CDN depending on language * * @since 1.3.0 * * @param bool $explaining * * @return string $url URL of */ public function get_icon_url( $explaining = false ) { $locale = get_locale(); $lang = substr( $locale, 0, 2 ); $logo_default = WOOGATE_URLPATH . 'images/klarna-logo.svg'; if ( 'de' === $lang ) { $url = $logo_default; // $url = $explaining ? 'https://cdn.klarna.com/1.0/shared/image/generic/badge/de_de/pay_now/descriptive/pink.svg' : 'https://cdn.klarna.com/1.0/shared/image/generic/badge/de_de/pay_now/standard/pink.svg'; } elseif ( 'en' === $lang ) { $url = $logo_default; // $url = $explaining ? 'https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/descriptive/pink.svg' : 'https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/standard/pink.svg'; } elseif ( 'es' === $lang ) { $url = $logo_default; // $url = $explaining ? 'https://cdn.klarna.com/1.0/shared/image/generic/badge/es_es/pay_now/descriptive/pink.svg' : 'https://cdn.klarna.com/1.0/shared/image/generic/badge/es_es/pay_now/standard/pink.svg'; } elseif ( 'fr' === $lang ) { $url = $explaining ? WOOGATE_URLPATH . 'images/klarna-logo-fr-explaining.svg' : WOOGATE_URLPATH . 'images/klarna-logo-fr.svg'; // $url = $explaining ? 'https://cdn.klarna.com/1.0/shared/image/generic/badge/fr_fr/pay_now/descriptive/pink.svg' : 'https://cdn.klarna.com/1.0/shared/image/generic/badge/fr_fr/pay_now/standard/pink.svg'; } else { $url = $logo_default; // $url = $explaining ? 'https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/descriptive/pink.svg' : 'https://cdn.klarna.com/1.0/shared/image/generic/badge/en_gb/pay_now/standard/pink.svg'; } return $url; } /** * Add all form fields * * @since 1.0.0 */ public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'woogate' ), 'type' => 'checkbox', 'label' => __( 'Enable Sofort Banking', 'woogate' ), 'default' => 'yes' ), 'title' => array( 'title' => __( 'Title', 'woogate' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'woogate' ), 'default' => __( 'Online bank transfer.', 'woogate' ) ), 'description' => array( 'title' => __( 'Description', 'woogate' ), 'type' => 'textarea', 'description' => __( 'This controls the description which the user sees during checkout.', 'woogate' ), 'default' => __( 'Simple and secure.', 'woogate' ) ), 'configkey' => array( 'title' => __( 'Config Key', 'woogate' ), 'type' => 'text', 'description' => __( 'You need to enter your configkey or userid:projektid:apikey', 'woogate' ), 'default' => '' ), 'notify_email' => array( 'title' => __( 'Notification email', 'woogate' ), 'type' => 'text', 'description' => __( 'Enter your email address if you would like to receive status changes for payments.', 'woogate' ), 'default' => '' ), 'transaction_reason_1' => array( 'title' => __( 'Transaction reason line 1', 'woogate' ), 'type' => 'text', 'description' => __( 'The transaction reason which will appear in the bank transaction (max. 40 chars including variable content, longer values will be cutted). You can use {{order_number}}, {{order_id}} and {{site_name}} as variable. ', 'woogate' ), 'default' => __( 'Order {{order_number}}', 'woogate' ), ), 'transaction_reason_2' => array( 'title' => __( 'Transaction reason line 2', 'woogate' ), 'type' => 'text', 'description' => __( 'The transaction reason which will appear in the bank transaction (max. 40 chars including variable content, longer values will be cutted). You can use {{order_number}}, {{order_id}} and {{site_name}} as variable. ', 'woogate' ), 'default' => '' ), 'trust_pending' => array( 'title' => __( 'Trust pending payments', 'woogate' ), 'type' => 'checkbox', 'label' => __( 'Accept payments from Online Bank Transfer with the status "pending" or "untraceable" (untraceable for users without "Deutsche Handelsbank" account) and sets order status to "In-Pogress".', 'woogate' ), 'default' => 'no' ), 'debug' => array( 'title' => __( 'Debug', 'woogate' ), 'type' => 'checkbox', 'label' => __( 'If you experience problems enable logging which will be logged in WordPress Admin > WooCommerce > System Status > Logs.', 'woogate' ), 'default' => 'no' ) ); } /** * Add an options panel to the Woocommerce settings * * @since 1.0.0 */ public function admin_options() { ?> <h3><?php _e( 'Online Bank Transfer.', 'woogate' ); ?></h3> <p><?php _e( 'Direct payment via online banking. Easy, quick and secure – without registration. Automatic data transfer and the real-time transaction notification enable a smooth payment process and a faster delivery.', 'woogate' ); ?></p> <?php echo '<table class="form-table">'; $this->generate_settings_html(); echo '</table>'; } /** * Check the response from Sofort.com * * @since 1.0.0 */ public function payment_listener() { /** * Get the configkey from the gateway settings and make it filterable. * * @since 1.2.0 * * @param string $this ->$configkey The Sofort configkey. */ $configkey = apply_filters( 'woogate_sofortgateway_configkey', $this->configkey ); $input = file_get_contents( 'php://input' ); $notification = new Notification(); $transaction_id = $notification->getNotification( $input ); $transaction_data = new TransactionData( $configkey ); if ( ! $transaction_id ) { $this->log( 'Payment Listener: Getting notification failed. No transaction id.' ); } $transaction_data->addTransaction( $transaction_id ); $transaction_data->setApiVersion( '2.0' ); $transaction_data->sendRequest(); $reason = $transaction_data->getStatusReason(); $order_id = $transaction_data->getUserVariable(); $status = $transaction_data->getStatus(); $order = new WC_Order( $order_id ); $this->log( 'Payment Listener: Updating status for order #' . $order_id . ' to "' . $status . '" with reason "' . $reason . '" by sofort.com' ); if ( (int) $order->get_id() !== (int) $order_id ) { $this->log( 'Payment Listener: Invalid request. Order ID #' . $order_id . ' not found."' ); wp_die( 'Invalid Request' ); } switch ( $status ) { /** * Waiting for payment */ case 'pending': if ( 'yes' === $this->trust_pending ) { $this->log( 'Payment Listener: Trusting payment in order #' . $order->get_id() ); $this->payment_completed( $order ); } else { $this->payment_pending( $order ); } break; /** * Payment cannot be verified technically, * because Sofort banking acccount is missing. */ case 'untraceable': // Trust pending payments to complete orders if ( 'yes' === $this->trust_pending ) { $this->log( 'Payment Listener: Trusting payment because of missing sofort banking account in order #' . $order->get_id() ); $this->payment_completed( $order ); } else { $this->payment_pending( $order ); } break; /** * Payment has not been received */ case 'loss': $this->payment_failed( $order ); break; /** * Payment has been refunded */ case 'refunded': $this->payment_refunded( $order ); break; /** * Payment has been received */ case 'received': if ( 'consumer_protection' === $reason ) { $this->payment_refunded( $order ); } elseif ( 'credited' === $reason ) { $this->payment_completed( $order ); } break; default : wp_die( 'Invalid Request' ); break; } } /** * Sets the payment to completed and adds further actions * * @since 1.2.0 * * @param WC_Order $order * @param string $reason Reason of sofort */ private function payment_completed( &$order ) { $order->payment_complete(); $order->add_order_note( sprintf( __( 'Payment completed for order %s via Sofort Banking.', 'woogate' ), $order->get_id() ) ); /** * Action after payment is completed * * @since 1.2.0 * * @param int $order_id */ do_action( 'woogate_sofort_payment_complete', $order->get_id() ); /** * Deprecated - Please do not use this post meta in future. This will be removed soon! * * @since 1.2.0 */ update_post_meta( $order->get_id(), 'Payer email address', $order->get_billing_email() ); update_post_meta( $order->get_id(), 'Transaction ID', $order->get_transaction_id() ); update_post_meta( $order->get_id(), 'Payer first name', $order->get_billing_first_name() ); update_post_meta( $order->get_id(), 'Payer last name', $order->get_billing_last_name() ); } /** * Sets the payment to refunded and adds further actions * * @since 1.2.0 * * @param WC_Order $order WooCommerce order object */ private function payment_refunded( &$order ) { if( $order->get_total_refunded() === $order->get_total() ) { $order->update_status( 'refunded', sprintf( __( 'Payment refunded for order %s via Sofort Banking.', 'woogate' ), $order->get_id() ) ); } /** * Action after payment has refunded * * @since 1.2.0 * * @param int $order_id WooCommerce Order id */ do_action( 'woogate_sofort_payment_refunded', $order->get_id() ); $wc_emails = WC_Emails::instance(); $message = $wc_emails->wrap_message( __( 'Order refunded', 'woogate' ), sprintf( __( 'Order #%s was refunded', 'woogate' ), $order->get_order_number() ) ); wc_mail( get_option( 'woocommerce_new_order_email_recipient' ), sprintf( __( 'Payment for order #%s refunded', 'woogate' ), $order->get_order_number() ), $message ); } /** * Sets the payment to failed and adds further actions * * @since 1.2.0 * * @param WC_Order $order */ private function payment_failed( &$order ) { $order->update_status( 'failed', sprintf( __( 'Payment failed for order %s via Sofort Banking.', 'woogate' ), $order->get_id() ) ); /** * Action after payment has failed * * @since 1.2.0 * * @param int $order_id WooCommerce Order id */ do_action( 'woogate_sofort_payment_failed', $order->get_id() ); } /** * Sets the payment to pending and adds further actions * * @since 1.2.0 * * @param WC_Order $order */ private function payment_pending( &$order ) { $order->update_status( 'pending', sprintf( __( 'Payment pending for order %s via Sofort Banking.', 'woogate' ), $order->get_id() ) ); /** * Action after payment is pending * * @since 1.2.0 * * @param int $order_id WooCommerce Order id */ do_action( 'woogate_sofort_payment_pending', $order->get_id() ); } /** * Sets the payment to pending and adds further actions * * @since 1.2.0 * * @param WC_Order $order WooCommerce Order id */ private function payment_initialized( &$order ) { $order->add_order_note( sprintf( __( 'Payment process with Online Bank Transfer was initialized (Transaction ID: %s).', 'woogate' ), $order->get_transaction_id() ) ); /** * Action after payment is pending * * @since 1.2.0 * * @param int $order_id WooCommerce Order id */ do_action( 'woogate_sofort_payment_initialized', $order->get_id() ); } /** * Even though we don't really have any fields * we still need to output something, otherwise * we get a fatal error * * @since 1.0.0 */ public function payment_fields() { $description = $this->get_description(); if ( ! empty( $description ) ) { echo wpautop( wptexturize( $description ) ); } } /** * Process the payment * * Does not really do anything, except redirect the user. * Order processing is done in self::payment_listener() * * @since 1.0.0 * * @param $order_id int Internal WP post ID * * @return array * */ public function process_payment( $order_id ) { $order = new WC_Order( $order_id ); $payment_amount = (float) number_format( $order->get_total(), 2, '.', '' ); $this->log( 'Generating payment link for order #' . $order->get_id() . '. Notify URL: ' . $this->callback ); /** * Get the configkey from the gateway settings and make it filterable. * * @since 1.1.16 * * @param string $this ->$configkey The Sofort configkey. */ $configkey = apply_filters( 'woogate_sofortgateway_configkey', $this->configkey ); $transaction_reason[0] = $this->get_transaction_reason( 1, $order ); $transaction_reason[1] = $this->get_transaction_reason( 2, $order ); $return_url = $this->get_return_url( $order ); $cancel_order_url = $order->get_cancel_order_url(); if ( empty( $transaction_reason[0] ) ) { $this->log( 'Transaction reason 1 must not be empty for order #' . $order->get_id() ); } $this->log( 'Return URL for order #' . $order->get_id() . ': ' . $return_url ); $this->log( 'Cancel URL for order #' . $order->get_id() . ': ' . $cancel_order_url ); /** * Get the notify email from the gateway settings and make it filterable. * * @since 1.1.16 * * @param string $this ->notify_email The notify email. */ $notify_email = apply_filters( 'woogate_sofortgateway_notify_email', $this->notify_email ); /** * Setting up payment for Sofort */ $sofort = new Sofortueberweisung( $configkey ); $sofort->setAmount( $payment_amount ); $sofort->setCurrencyCode( get_woocommerce_currency() ); $sofort->setReason( $transaction_reason[0], $transaction_reason[1] ); $sofort->setNotificationUrl( $this->callback ); $sofort->setSuccessUrl( $return_url ); $sofort->setAbortUrl( $cancel_order_url ); $sofort->setUserVariable( $order->get_id() ); $sofort->setEmailCustomer( $order->get_billing_email() ); if ( ! empty( $notify_email ) ) { $sofort->setNotificationEmail( $notify_email ); } /** * Timeout how long this transaction configuration will be valid for this is the time between the generation of the * payment url and the user completing the form, should be at least two to three minutes defaults to unlimited if * not set * * @since 1.2.0 * * @param int $payment_timeout Timeout for payment in seconds */ $payment_timeout = apply_filters( 'woogate_sofortgateway_payment_timeout', false ); if ( false !== $payment_timeout ) { $sofort->setTimeout( $payment_timeout ); } /** * Force the sofort payment process language * * @since 1.3.0 * * @param int $language_code Language code (ISO 639-1) */ $language_code = apply_filters( 'woogate_sofortgateway_language_code', false ); if ( false !== $language_code ) { $this->log( 'Forced language code in order #' . $order->get_id() . ' to: ' . $language_code ); $sofort->setLanguageCode( $language_code ); } /** * Sending request to sofort.com */ $sofort->sendRequest(); if ( $sofort->isError() ) { $this->log( 'Link generation error for order #' . $order->get_id() . '. Error: ' . $sofort->getError() ); wc_add_notice( sprintf( __( 'Sofort Banking could not get contacted. Please contact the site admin at %s or choose another payment method.', 'woogate' ), get_option( 'admin_email' ) ), 'error' ); /** * Action after payment initialization ha failed * * @since 1.2.0 * * @param int $order_id */ do_action( 'woogate_sofort_payment_request_error', $order->get_id() ); return array( 'result' => 'error', 'redirect' => $cancel_order_url ); } else { try{ $order->set_transaction_id( $sofort->getTransactionId() ); } catch ( WC_Data_Exception $e ) { $this->log( 'Could not set transaction ID for order #' . $order->get_id() . '. Error: ' . $e->getMessage() ); } $order->save(); $this->payment_initialized( $order ); /** * Action after payment initialization succeded * * @since 1.2.0 * * @param int $order_id */ do_action( 'woogate_sofort_payment_request_succeeded', $order->get_id() ); return array( 'result' => 'success', 'redirect' => $sofort->getPaymentUrl() ); } } /** * Get transaction reason * * @param int $number Transaction reason number 1 or 2 * @param WC_Order $order Order object * * @return string $transaction_reason Transaction reason * * @since 1.4.0 */ public function get_transaction_reason( $number, $order ) { $property_name = 'transaction_reason_' . $number; $transaction_reason = $this->replace_template_tags( $this->$property_name, $order ); /** * Get the transaction reason and make it filterable. * * @since 1.1.18 * * @param string $transaction_reason Transaction reason * @param WC_Order $order Order object */ $transaction_reason = apply_filters( 'woogate_sofort_transaction_reason_' . $number, $transaction_reason, $order ); if( strlen( $transaction_reason ) > 40 ) { $this->log( 'Transaction reason too long for order #' . $order->get_id() . ' ("' . $transaction_reason . '"). Cutted transaction reason to 40 chars.' ); $transaction_reason = substr( $transaction_reason, 0, 40 ); } return $transaction_reason; } /** * Replacing template tags used in Settings * * @param string $string String with variables which have to be replaced * @param WC_Order $order Order object * * @return string $string * * @since 1.4.0 */ public function replace_template_tags( $string, $order ) { $string = str_replace( '{{order_number}}', $order->get_order_number(), $string ); $string = str_replace( '{{order_id}}', $order->get_id(), $string ); $string = str_replace( '{{site_name}}', get_bloginfo( 'name' ), $string ); return $string; } /** * Can the order be refunded? * * @since 1.2.0 * * @param WC_Order $order * * @return bool */ public function can_refund_order( $order ) { return $order && $order->get_transaction_id(); } /** * Process a refund if supported. * * @since 1.2.0 * * @param int $order_id * @param float $amount * @param string $reason * * @return bool|WP_Error */ public function process_refund( $order_id, $amount = null, $reason = '' ) { $order = new WC_Order( $order_id ); if ( ! $this->can_refund_order( $order ) ) { $this->log( 'Refund Failed for transaction id ' . $order->get_transaction_id() . ' in order ' . $order_id ); return new WP_Error( 'error', sprintf( __( 'Refund failed. Transaction ID %s in order %s', 'woogate' ), $order->get_transaction_id(), $order_id ) ); } /** * Get the configkey from the gateway settings and make it filterable. * * @since 1.2.0 * * @param string $this ->$configkey The Sofort configkey. */ $configkey = apply_filters( 'woogate_sofortgateway_configkey', $this->configkey ); $refund = new Refund( $configkey ); $refund->addRefund( $order->get_transaction_id(), $amount, $reason ); $refund->sendRequest(); if ( $refund->isError() ) { $this->log( 'Refund failed for order #' . $order->get_id() . '. Error: ' . $refund->getError() ); return false; } else { $order->add_order_note( sprintf( __( 'Refunded %s to transaction %s with the reason: %s', 'woogate' ), $amount, $order->get_transaction_id(), $reason ) ); $this->log( 'Refund succeeded for order #' . $order->get_id() . '. Amount: ' . $amount ); return true; } } /** * Logging wrapper function * * @since 1.2.0 * * @param string $string * * @return bool */ public function log( $string ) { if ( ! is_object( $this->logger ) ) { $this->logger = new WC_Logger(); } if ( $this->debug === 'yes' ) { $this->logger->add( 'sofortgateway', $string ); return true; } return false; } } } /** * Add to the gateways array * * Can't be part of the class as this function basically * registers the gateway * * @since 1.0.0 * * @param array $methods Holds all registered gateway options * * @return array $methods */ function woogate_add_payment_gateway( $methods ) { $methods[] = 'WooCommerce_Sofortueberweisung'; return $methods; } add_filter( 'woocommerce_payment_gateways', 'woogate_add_payment_gateway' );
- The topic ‘order_number vs order_id in sofort payment gateway plugin modification’ is closed to new replies.