first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,538 @@
<?php
/**
* Revolut Helper
*
* Helper class for required tools.
*
* @package WooCommerce
* @category Payment Gateways
* @author Revolut
* @since 2.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WC_Gateway_Revolut_Helper_Trait trait.
*/
trait WC_Gateway_Revolut_Express_Checkout_Helper_Trait {
/**
* Free shipping.
*
* @var array
*/
public static $free_shipping = array(
array(
'id' => 'free_shipping',
'amount' => '0',
'description' => '',
'label' => 'SHIPPING',
),
);
/**
* Calculate shipping
*
* @param array $address customer address info.
*/
public function calculate_shipping( $address = array() ) {
$country = $address['country'];
$state = $this->convert_state_name_to_id( $address['country'], $address['state'] );
$postcode = $address['postcode'];
$city = $address['city'];
$address_1 = $address['address'];
$address_2 = $address['address_2'];
WC()->shipping->reset_shipping();
if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) {
$postcode = wc_format_postcode( $postcode, $country );
}
if ( $country ) {
WC()->customer->set_location( $country, $state, $postcode, $city );
WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
} else {
WC()->customer->set_billing_address_to_base();
WC()->customer->set_shipping_address_to_base();
}
WC()->customer->set_calculated_shipping( true );
WC()->customer->save();
$packages = array();
$package = array();
$package['contents'] = WC()->cart->get_cart();
$package['contents_cost'] = 0;
$package['applied_coupons'] = WC()->cart->applied_coupons;
$package['user']['ID'] = get_current_user_id();
$package['destination']['country'] = $country;
$package['destination']['state'] = $state;
$package['destination']['postcode'] = $postcode;
$package['destination']['city'] = $city;
$package['destination']['address'] = $address_1;
$package['destination']['address_2'] = $address_2;
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['data']->needs_shipping() ) {
if ( isset( $item['line_total'] ) ) {
$package['contents_cost'] += $item['line_total'];
}
}
}
$packages[0] = $package;
$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
WC()->shipping->calculate_shipping( $packages );
}
/**
* Get shipping options
*
* @param array $shipping_address customer address info.
*/
public function get_shipping_options( $shipping_address ) {
$shipping_options = array();
$GLOBALS['wp']->query_vars['rest_route'] = 'wc/store/v3/cart';
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
$this->calculate_shipping( $shipping_address );
WC()->cart->calculate_totals();
$packages = WC()->shipping->get_packages();
if ( empty( $packages ) && ! WC()->customer->has_calculated_shipping() ) {
return $shipping_options;
}
$package = $packages[0];
if ( empty( $package ) || empty( $package['rates'] ) ) {
return $shipping_options;
}
foreach ( $package['rates'] as $rate ) {
$shipping_cost = (float) $rate->get_cost() + (float) $rate->get_shipping_tax();
$shipping_cost = wc_format_decimal( $shipping_cost, wc_get_price_decimals() );
$shipping_options[] = array(
'id' => $rate->id,
'label' => $rate->label . ' ' . $shipping_cost . ' ' . get_woocommerce_currency(),
'description' => '',
'amount' => $shipping_cost * 100,
);
}
if ( isset( $shipping_options[0] ) ) {
if ( isset( $chosen_shipping_methods[0] ) ) {
$chosen_method_id = $chosen_shipping_methods[0];
$compare_shipping_options = function ( $a, $b ) use ( $chosen_method_id ) {
if ( $a['id'] === $chosen_method_id ) {
return -1;
}
if ( $b['id'] === $chosen_method_id ) {
return 1;
}
return 0;
};
usort( $shipping_options, $compare_shipping_options );
}
$first_shipping_method_id = $shipping_options[0]['id'];
$this->update_shipping_method( array( $first_shipping_method_id ) );
}
WC()->cart->calculate_totals();
return $shipping_options;
}
/**
* Update shipping method in WC cart.
*
* @param array $shipping_methods shipping method list.
*/
public function update_shipping_method( $shipping_methods ) {
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
if ( is_array( $shipping_methods ) ) {
foreach ( $shipping_methods as $i => $value ) {
$chosen_shipping_methods[ $i ] = wc_clean( $value );
}
}
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
WC()->cart->calculate_totals();
}
/**
* Get Required parameters for Revolut order.
*/
public function get_revolut_order_descriptor() {
if ( $this->is_product() ) {
$product = $this->get_product_data();
return new WC_Revolut_Order_Descriptor( $product['productPrice'], get_woocommerce_currency(), null );
}
return new WC_Revolut_Order_Descriptor( WC()->cart->get_total( '' ), get_woocommerce_currency(), null );
}
/**
* Check is product page.
*/
public function is_product() {
if ( is_product() || wc_post_content_has_shortcode( 'product_page' ) ) {
$product = $this->get_product();
if ( 'subscription' !== $product->get_type() ) {
return true;
}
}
return false;
}
/**
* Get product data.
*/
public function get_product_data() {
if ( ! $this->is_product() ) {
return false;
}
$product = $this->get_product();
if ( 'variable' === $product->get_type() ) {
$variation_attributes = $product->get_variation_attributes();
$attributes = array();
foreach ( $variation_attributes as $attribute_name => $attribute_values ) {
$attribute_key = 'attribute_' . sanitize_title( $attribute_name );
if ( $this->check_is_get_data_submitted( $attribute_key ) ) {
$attributes[ $attribute_key ] = sanitize_text_field( wp_unslash( $_GET[ $attribute_key ] ) ); // phpcs:ignore
} else {
$attributes[ $attribute_key ] = $product->get_variation_default_attribute( $attribute_name );
}
}
$data_store = WC_Data_Store::load( 'product' );
$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
if ( ! empty( $variation_id ) ) {
$product = wc_get_product( $variation_id );
}
}
$data = array();
$data['productPrice'] = $this->get_product_price( $product );
$data['shipping_required'] = ( wc_shipping_enabled() && $product->needs_shipping() && 0 !== wc_get_shipping_method_count( true ) );
return $data;
}
/**
* Get product price
*
* @param object $product WooCommerce product.
*/
public function get_product_price( $product ) {
$product_price = $product->get_price();
if ( 'subscription' === $product->get_type() && class_exists( 'WC_Subscriptions_Product' ) ) {
$product_price = $product->get_price() + WC_Subscriptions_Product::get_sign_up_fee( $product );
}
return $product_price;
}
/**
* Get product object.
*/
public function get_product() {
global $post;
if ( is_product() ) {
return wc_get_product( $post->ID );
} elseif ( wc_post_content_has_shortcode( 'product_page' ) ) {
// Get id from product_page shortcode.
preg_match( '/\[product_page id="(?<id>\d+)"\]/', $post->post_content, $shortcode_match );
if ( ! isset( $shortcode_match['id'] ) ) {
return false;
}
return wc_get_product( $shortcode_match['id'] );
}
return false;
}
/**
* Get redirect URL.
*/
public function get_redirect_url() {
global $post;
if ( is_product() ) {
return get_permalink( $post->ID );
} elseif ( wc_post_content_has_shortcode( 'product_page' ) ) {
// Get id from product_page shortcode.
preg_match( '/\[product_page id="(?<id>\d+)"\]/', $post->post_content, $shortcode_match );
if ( isset( $shortcode_match['id'] ) ) {
return get_permalink( $shortcode_match['id'] );
}
}
if ( is_cart() ) {
return wc_get_cart_url();
}
return wc_get_checkout_url();
}
/**
* Get parameters
*/
public function get_wc_revolut_payment_request_params() {
try {
$revolut_public_id = $this->create_express_checkout_public_id();
$total = WC()->cart->get_total( '' );
$currency = get_woocommerce_currency();
$total = $this->get_revolut_order_total( $total, $currency );
$revolut_payment_request_settings = get_option( 'woocommerce_revolut_payment_request_settings', array() );
$revolut_pay_settings = get_option( 'woocommerce_revolut_pay_settings', array() );
return array(
'total' => $total,
'currency' => $currency,
'locale' => $this->get_lang_iso_code(),
'publicToken' => $this->get_merchant_public_api_key(),
'ajax_url' => WC_AJAX::get_endpoint( '%%wc_revolut_gateway_ajax_endpoint%%' ),
'revolut_public_id' => $revolut_public_id,
'revolut_pay_origin_url' => str_replace( array( 'https://', 'http://' ), '', get_site_url() ),
'revolut_pay_button_theme' => ! empty( $revolut_pay_settings['revolut_pay_button_theme'] ) ? $revolut_pay_settings['revolut_pay_button_theme'] : '',
'revolut_pay_button_size' => ! empty( $revolut_pay_settings['revolut_pay_button_size'] ) ? $revolut_pay_settings['revolut_pay_button_size'] : '',
'revolut_pay_button_radius' => ! empty( $revolut_pay_settings['revolut_pay_button_radius'] ) ? $revolut_pay_settings['revolut_pay_button_radius'] : '',
'payment_request_button_type' => ! empty( $revolut_payment_request_settings['payment_request_button_type'] ) ? $revolut_payment_request_settings['payment_request_button_type'] : '',
'payment_request_button_theme' => ! empty( $revolut_payment_request_settings['payment_request_button_theme'] ) ? $revolut_payment_request_settings['payment_request_button_theme'] : '',
'payment_request_button_radius' => ! empty( $revolut_payment_request_settings['payment_request_button_radius'] ) ? $revolut_payment_request_settings['payment_request_button_radius'] : '',
'payment_request_button_size' => ! empty( $revolut_payment_request_settings['payment_request_button_size'] ) ? $revolut_payment_request_settings['payment_request_button_size'] : '',
'shipping_options' => array(),
'nonce' => array(
'payment' => wp_create_nonce( 'wc-revolut-payment-request' ),
'shipping' => wp_create_nonce( 'wc-revolut-payment-request-shipping' ),
'update_shipping' => wp_create_nonce( 'wc-revolut-update-shipping-method' ),
'update_order_total' => wp_create_nonce( 'wc-revolut-update-order-total' ),
'load_order_data' => wp_create_nonce( 'wc-revolut-load-order-data' ),
'cancel_order' => wp_create_nonce( 'wc-revolut-cancel-order' ),
'get_express_checkout_params' => wp_create_nonce( 'wc-revolut-get-express-checkout-params' ),
'get_payment_request_params' => wp_create_nonce( 'wc-revolut-get-payment-request-params' ),
'checkout' => wp_create_nonce( 'woocommerce-process_checkout' ),
'add_to_cart' => wp_create_nonce( 'wc-revolut-pr-add-to-cart' ),
'get_selected_product_data' => wp_create_nonce( 'wc-revolut-get-selected-product-data' ),
'log_errors' => wp_create_nonce( 'wc-revolut-log-errors' ),
'clear_cart' => wp_create_nonce( 'wc-revolut-clear-cart' ),
),
'is_product_page' => $this->is_product(),
'redirect_url' => $this->get_redirect_url(),
'is_cart_page' => is_cart(),
'product' => $this->get_product_data(),
'shipping_required' => $this->is_shipping_required(),
'free_shipping_option' => self::$free_shipping,
'error_messages' => array(
'checkout_general' => __( 'Something went wrong while processing the order. Please try again', 'revolut-gateway-for-woocommerce' ),
'cart_create_failed' => __( 'An error occurred while creating WooCommerce cart', 'revolut-gateway-for-woocommerce' ),
),
);
} catch ( Exception $e ) {
$this->log_error( $e->getMessage() );
}
}
/**
* Create Revolut order for express checkout.
*/
public function create_express_checkout_public_id() {
$revolut_public_id = $this->get_revolut_express_checkout_public_id();
$descriptor = $this->get_revolut_order_descriptor();
if ( null === $revolut_public_id ) {
$revolut_public_id = $this->create_revolut_order( $descriptor, true );
$this->set_revolut_express_checkout_public_id( $revolut_public_id );
} else {
$revolut_public_id = $this->update_revolut_order( $descriptor, $revolut_public_id, true );
$this->set_revolut_express_checkout_public_id( $revolut_public_id );
}
return $revolut_public_id;
}
/**
* Check if shipping required for the order.
*/
public function is_shipping_required() {
if ( $this->is_product() ) {
$product = $this->get_product_data();
return isset( $product['shipping_required'] ) ? $product['shipping_required'] : false;
}
if ( is_cart() ) {
return ! is_null( WC()->cart ) && WC()->cart->needs_shipping();
}
return false;
}
/**
* Check is page supports payment request button
*
* @param array $payment_request_button_locations configuration.
*/
public function page_supports_payment_request_button( $payment_request_button_locations ) {
if ( empty( $payment_request_button_locations ) ) {
$payment_request_button_locations = array();
}
if ( ! is_cart() && ! $this->is_product() ) {
return false;
}
if ( $this->is_product() && ! in_array( 'product', $payment_request_button_locations, true ) ) {
return false;
}
if ( is_cart() && ! in_array( 'cart', $payment_request_button_locations, true ) ) {
return false;
}
if ( $this->is_subscription_product() ) {
return false;
}
if ( ! $this->check_order_creation_possible() ) {
return false;
}
return true;
}
/**
* Check is subscription product.
*/
public function is_subscription_product() {
if ( ! class_exists( 'WC_Subscriptions_Product' ) ) {
return false;
}
if ( $this->is_product() ) {
$product = $this->get_product();
if ( WC_Subscriptions_Product::is_subscription( $product ) ) {
return true;
}
}
if ( is_cart() ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
if ( WC_Subscriptions_Product::is_subscription( $_product ) ) {
return true;
}
}
}
return false;
}
/**
* Check is creating WooCommerce order possible.
*/
public function check_order_creation_possible() {
if ( is_user_logged_in() || ! $this->check_authentication_required() ) {
return true;
}
return false;
}
/**
* Covert Revolut address type into the required form of express checkout.
*
* @param array $address from api.
*/
public function convert_revolut_address_to_express_checkout_address( $address ) {
$address['country'] = $address['country_code'];
$address['addressLine'] = array( $address['street_line_1'], '' );
$address['address'] = $address['street_line_1'];
$address['address_2'] = '';
$address['postalCode'] = $address['postcode'];
$address['region'] = ! empty( $address['region'] ) ? $address['region'] : '';
$address['state'] = $address['region'];
return $address;
}
/**
* Check if authentication is required.
*/
public function check_authentication_required() {
if ( 'no' === get_option( 'woocommerce_enable_guest_checkout', 'yes' ) && ! $this->check_account_creation_possible() ) {
return true;
}
return false;
}
/**
* Check if account creation possible
*/
public function check_account_creation_possible() {
return (
'yes' === get_option( 'woocommerce_enable_signup_and_login_from_checkout', 'no' ) &&
'yes' === get_option( 'woocommerce_registration_generate_username', 'yes' ) &&
'yes' === get_option( 'woocommerce_registration_generate_password', 'yes' )
);
}
/**
* Load sate id by name if the api sends state name.
*
* @param string $country_id id country.
* @param string $state_name state name.
*/
public function convert_state_name_to_id( $country_id, $state_name ) {
$wc_states = WC()->countries->get_states( $country_id );
if ( empty( $wc_states ) || empty( $state_name ) ) {
return $state_name;
}
foreach ( $wc_states as $state_id => $wc_state_name ) {
if ( strtolower( $wc_state_name ) === strtolower( $state_name ) || strtolower( $state_id ) === strtolower( $state_name ) ) {
return $state_id;
}
}
// if the standard search fails search county by removing Co prefix for Irish states.
if ( 'IE' === $country_id ) {
$state_name = str_replace( 'Co. ', '', $state_name );
foreach ( $wc_states as $state_id => $wc_state_name ) {
if ( strtolower( $wc_state_name ) === strtolower( $state_name ) || strtolower( $state_id ) === strtolower( $state_name ) ) {
return $state_id;
}
}
}
return $state_name;
}
}

View File

@@ -0,0 +1,948 @@
<?php
/**
* Revolut Helper
*
* Helper class for required tools.
*
* @package WooCommerce
* @category Payment Gateways
* @author Revolut
* @since 2.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WC_Gateway_Revolut_Helper_Trait trait.
*/
trait WC_Gateway_Revolut_Helper_Trait {
use WC_Revolut_Settings_Trait;
use WC_Revolut_Logger_Trait;
/**
* Create Revolut Order
*
* @param WC_Revolut_Order_Descriptor $order_descriptor Revolut Order Descriptor.
*
* @param bool $is_express_checkout indicator.
*
* @return mixed
* @throws Exception Exception.
*/
public function create_revolut_order( WC_Revolut_Order_Descriptor $order_descriptor, $is_express_checkout = false ) {
$capture = 'authorize' === $this->api_settings->get_option( 'payment_action' ) || $is_express_checkout ? 'manual' : 'automatic';
$body = array(
'amount' => $order_descriptor->amount,
'currency' => $order_descriptor->currency,
'capture_mode' => $capture,
);
if ( ! empty( $order_descriptor->revolut_customer_id ) ) {
$body['customer'] = array( 'id' => $order_descriptor->revolut_customer_id );
}
if ( $is_express_checkout ) {
$body['cancel_authorised_after'] = WC_REVOLUT_AUTO_CANCEL_TIMEOUT;
$location_id = $this->api_settings->get_revolut_location();
if ( $location_id ) {
$body['location_id'] = $location_id;
}
}
$json = $this->api_client->post( '/orders', $body, false, true );
if ( isset( $json['token'] ) ) {
$json['public_id'] = $json['token'];
}
if ( empty( $json['id'] ) || empty( $json['public_id'] ) ) {
throw new Exception( 'Something went wrong: ' . wp_json_encode( $json, JSON_PRETTY_PRINT ) );
}
global $wpdb;
$result = $wpdb->query(
$wpdb->prepare(
'INSERT INTO ' . $wpdb->prefix . "wc_revolut_orders (order_id, public_id)
VALUES (UNHEX(REPLACE(%s, '-', '')), UNHEX(REPLACE(%s, '-', '')))",
array(
$json['id'],
$json['public_id'],
)
)
); // db call ok; no-cache ok.
if ( 1 !== $result ) {
throw new Exception( 'Can not save Revolut order record on DB:' . $wpdb->last_error );
}
if ( $is_express_checkout ) {
$this->add_or_update_temp_session( $json['id'] );
}
return $json['public_id'];
}
/**
* Retrieve the revolut customer's id.
*
* @param string $billing_phone holds customer email address.
* @param string $billing_email holds customer billing phone.
* @throws Exception Exception.
*/
public function get_or_create_revolut_customer( $billing_phone = '', $billing_email = '' ) {
if ( empty( $billing_email ) || empty( $billing_phone ) ) {
$wc_customer = WC()->customer;
$billing_email = $wc_customer->get_billing_email();
$billing_phone = $wc_customer->get_billing_phone();
}
if ( empty( $billing_email ) || empty( $billing_phone ) ) {
return;
}
$revolut_customer_id = $this->get_revolut_customer_id();
if ( empty( $revolut_customer_id ) ) {
$revolut_customer_id = $this->create_revolut_customer( $billing_phone, $billing_email );
return $revolut_customer_id;
}
return $revolut_customer_id;
}
/**
* Update the revolut customer's phone.
*
* @param string $revolut_customer_id customer_id.
* @param string $billing_phone billing phone number.
* @throws Exception Exception.
* @return void|null
*/
public function update_revolut_customer( $revolut_customer_id, $billing_phone ) {
if ( empty( $revolut_customer_id ) || empty( $billing_phone ) ) {
return null;
}
$this->api_client->patch( "/customers/$revolut_customer_id", array( 'phone' => $billing_phone ) );
}
/**
* Create revolut customer.
*
* @return $revolut_customer_id revolut customer id.
* @param string $billing_phone holds customer billing phone.
* @param string $billing_email holds customer email address.
* @throws Exception Exception.
*/
public function create_revolut_customer( $billing_phone, $billing_email ) {
try {
if ( empty( $billing_phone ) || empty( $billing_email ) ) {
return;
}
$revolut_customer_id = null;
$body = array(
'phone' => $billing_phone,
'email' => $billing_email,
);
$revolut_customer = $this->api_client->get( '/customers?term=' . $billing_email );
$revolut_customer_id = ! empty( $revolut_customer[0]['id'] ) ? $revolut_customer[0]['id'] : '';
if ( ! $revolut_customer_id ) {
$revolut_customer = $this->api_client->post( '/customers', $body );
$revolut_customer_id = ! empty( $revolut_customer['id'] ) ? $revolut_customer['id'] : '';
}
if ( ! $revolut_customer_id ) {
return $revolut_customer_id;
}
$this->insert_revolut_customer_id( $revolut_customer_id );
$this->update_revolut_customer( $revolut_customer_id, $billing_phone );
return $revolut_customer_id;
} catch ( Exception $e ) {
$this->log_error( 'create_revolut_customer: ' . $e->getMessage() );
}
}
/**
* Save Revolut customer id.
*
* @param string $revolut_customer_id Revolut customer id.
*
* @throws Exception Exception.
*/
protected function insert_revolut_customer_id( $revolut_customer_id ) {
if ( empty( get_current_user_id() ) ) {
return;
}
global $wpdb;
$revolut_customer_id = "{$this->api_client->mode}_$revolut_customer_id";
$wpdb->query(
$wpdb->prepare(
"INSERT INTO {$wpdb->prefix}wc_revolut_customer (wc_customer_id, revolut_customer_id)
VALUES (%d, %s) ON DUPLICATE KEY UPDATE wc_customer_id = VALUES(wc_customer_id)",
array( get_current_user_id(), $revolut_customer_id )
)
); // db call ok; no-cache ok.
}
/**
* Update Revolut Order.
*
* @param WC_Revolut_Order_Descriptor $order_descriptor Revolut Order Descriptor.
* @param String $public_id Revolut public id.
* @param Bool $is_revpay_express_checkout is revpay express checkout.
*
* @return mixed
* @throws Exception Exception.
*/
public function update_revolut_order( WC_Revolut_Order_Descriptor $order_descriptor, $public_id, $is_revpay_express_checkout = false ) {
$order_id = $this->get_revolut_order_by_public_id( $public_id );
$body = array(
'amount' => $order_descriptor->amount,
'currency' => $order_descriptor->currency,
'customer_id' => $order_descriptor->revolut_customer_id,
);
if ( empty( $order_id ) ) {
return $this->create_revolut_order( $order_descriptor, $is_revpay_express_checkout );
}
$revolut_order = $this->api_client->get( "/orders/$order_id" );
if ( ! isset( $revolut_order['public_id'] ) || ! isset( $revolut_order['id'] ) || 'PENDING' !== $revolut_order['state'] ) {
return $this->create_revolut_order( $order_descriptor, $is_revpay_express_checkout );
}
$revolut_order = $this->api_client->patch( "/orders/$order_id", $body );
if ( ! isset( $revolut_order['public_id'] ) || ! isset( $revolut_order['id'] ) ) {
return $this->create_revolut_order( $order_descriptor, $is_revpay_express_checkout );
}
if ( $is_revpay_express_checkout ) {
$this->add_or_update_temp_session( $revolut_order['id'] );
}
return $revolut_order['public_id'];
}
/**
* Convert saved customer session into current session.
*
* @param string $id_revolut_order Revolut order id.
*
* @return void.
*/
public function convert_revolut_order_metadata_into_wc_session( $id_revolut_order ) {
WC()->initialize_session();
WC()->initialize_cart();
global $wpdb;
$temp_session = $wpdb->get_row( $wpdb->prepare( 'SELECT temp_session FROM ' . $wpdb->prefix . 'wc_revolut_temp_session WHERE order_id=%s', array( $id_revolut_order ) ), ARRAY_A ); // db call ok; no-cache ok.
$this->log_info( 'start convert_revolut_order_metadata_into_wc_session temp_session:' );
$this->log_info( $temp_session['temp_session'] );
$wc_order_metadata = json_decode( $temp_session['temp_session'], true );
$id_wc_customer = (int) $wc_order_metadata['id_customer'];
if ( $id_wc_customer ) {
wp_set_current_user( $id_wc_customer );
}
WC()->session->set( 'cart', $wc_order_metadata['cart'] );
WC()->session->set( 'cart_totals', $wc_order_metadata['cart_totals'] );
WC()->session->set( 'applied_coupons', $wc_order_metadata['applied_coupons'] );
WC()->session->set( 'coupon_discount_totals', $wc_order_metadata['coupon_discount_totals'] );
WC()->session->set( 'coupon_discount_tax_totals', $wc_order_metadata['coupon_discount_tax_totals'] );
WC()->session->set( 'get_removed_cart_contents', $wc_order_metadata['get_removed_cart_contents'] );
$session = new WC_Cart_Session( WC()->cart );
$session->get_cart_from_session();
}
/**
* Get order details
*
* @param array $address Customer address.
* @param bool $shipping_required is shipping option required for the current order.
* @param string $gateway selected payment gateway.
* @throws Exception Exception.
*/
public function format_wc_order_details( $address, $shipping_required, $gateway ) {
if ( empty( $address['billingAddress'] ) ) {
throw new Exception( 'Billing address is missing' );
}
if ( $shipping_required && empty( $address['shippingAddress'] ) ) {
throw new Exception( 'Shipping address is missing' );
}
if ( empty( $address['email'] ) ) {
throw new Exception( 'User Email information is missing' );
}
$revolut_billing_address = $address['billingAddress'];
$revolut_customer_email = $address['email'];
$revolut_customer_full_name = ! empty( $revolut_billing_address['recipient'] ) ? $revolut_billing_address['recipient'] : '';
$revolut_customer_billing_phone = ! empty( $revolut_billing_address['phone'] ) ? $revolut_billing_address['phone'] : '';
$revolut_customer_shipping_phone = '';
$wc_shipping_address = array();
list($billing_firstname, $billing_lastname) = $this->parse_customer_name( $revolut_customer_full_name );
if ( isset( $address['shippingAddress'] ) && ! empty( $address['shippingAddress'] ) ) {
$revolut_shipping_address = $address['shippingAddress'];
$revolut_customer_shipping_phone = ! empty( $revolut_shipping_address['phone'] ) ? $revolut_shipping_address['phone'] : '';
$revolut_customer_shipping_full_name = ! empty( $revolut_shipping_address['recipient'] ) ? $revolut_shipping_address['recipient'] : '';
$shipping_firstname = $billing_firstname;
$shipping_lastname = $billing_lastname;
if ( ! empty( $revolut_customer_shipping_full_name ) ) {
list($shipping_firstname, $shipping_lastname) = $this->parse_customer_name( $revolut_customer_shipping_full_name );
}
if ( empty( $revolut_customer_shipping_phone ) && ! empty( $revolut_customer_billing_phone ) ) {
$revolut_customer_shipping_phone = $revolut_customer_billing_phone;
}
$wc_shipping_address = $this->get_wc_shipping_address( $revolut_shipping_address, $revolut_customer_email, $revolut_customer_shipping_phone, $shipping_firstname, $shipping_lastname );
}
if ( empty( $revolut_customer_billing_phone ) && ! empty( $revolut_customer_shipping_phone ) ) {
$revolut_customer_billing_phone = $revolut_customer_shipping_phone;
}
$wc_billing_address = $this->get_wc_billing_address( $revolut_billing_address, $revolut_customer_email, $revolut_customer_billing_phone, $billing_firstname, $billing_lastname );
if ( $shipping_required ) {
$wc_order_data = array_merge( $wc_billing_address, $wc_shipping_address );
} else {
$wc_order_data = $wc_billing_address;
}
$wc_order_data['ship_to_different_address'] = $shipping_required;
$wc_order_data['revolut_pay_express_checkout'] = 'revolut_pay' === $gateway;
$wc_order_data['terms'] = 1;
$wc_order_data['order_comments'] = '';
return $wc_order_data;
}
/**
* Get first and lastname from customer full name string.
*
* @param string $full_name Customer full name.
*/
public function parse_customer_name( $full_name ) {
$full_name_list = explode( ' ', $full_name );
if ( count( $full_name_list ) > 1 ) {
$lastname = array_pop( $full_name_list );
$firstname = implode( ' ', $full_name_list );
return array( $firstname, $lastname );
}
$firstname = $full_name;
$lastname = 'undefined';
return array( $firstname, $lastname );
}
/**
* Create billing address for order.
*
* @param array $shipping_address Shipping address.
* @param string $revolut_customer_email Email.
* @param string $revolut_customer_phone Phone.
* @param string $firstname Firstname.
* @param string $lastname Lastname.
*/
public function get_wc_shipping_address( $shipping_address, $revolut_customer_email, $revolut_customer_phone, $firstname, $lastname ) {
if ( isset( $shipping_address['country'] ) ) {
$shipping_address['country'] = strtoupper( $shipping_address['country'] );
}
$address['shipping_first_name'] = $firstname;
$address['shipping_last_name'] = $lastname;
$address['shipping_email'] = $revolut_customer_email;
$address['shipping_phone'] = $revolut_customer_phone;
$address['shipping_country'] = ! empty( $shipping_address['country'] ) ? $shipping_address['country'] : '';
$address['shipping_address_1'] = ! empty( $shipping_address['addressLine'][0] ) ? $shipping_address['addressLine'][0] : '';
$address['shipping_address_2'] = ! empty( $shipping_address['addressLine'][1] ) ? $shipping_address['addressLine'][1] : '';
$address['shipping_city'] = ! empty( $shipping_address['city'] ) ? $shipping_address['city'] : '';
$address['shipping_state'] = ! empty( $shipping_address['region'] ) ? $this->convert_state_name_to_id( $shipping_address['country'], $shipping_address['region'] ) : '';
$address['shipping_postcode'] = ! empty( $shipping_address['postalCode'] ) ? $shipping_address['postalCode'] : '';
$address['shipping_company'] = '';
return $address;
}
/**
* Create billing address for order.
*
* @param array $billing_address Billing address.
* @param string $revolut_customer_email Email.
* @param string $revolut_customer_phone Phone.
* @param string $firstname Firstname.
* @param string $lastname Lastname.
*/
public function get_wc_billing_address( $billing_address, $revolut_customer_email, $revolut_customer_phone, $firstname, $lastname ) {
if ( isset( $billing_address['country'] ) ) {
$billing_address['country'] = strtoupper( $billing_address['country'] );
}
$address = array();
$address['billing_first_name'] = $firstname;
$address['billing_last_name'] = $lastname;
$address['billing_email'] = $revolut_customer_email;
$address['billing_phone'] = $revolut_customer_phone;
$address['billing_country'] = ! empty( $billing_address['country'] ) ? $billing_address['country'] : '';
$address['billing_address_1'] = ! empty( $billing_address['addressLine'][0] ) ? $billing_address['addressLine'][0] : '';
$address['billing_address_2'] = ! empty( $billing_address['addressLine'][1] ) ? $billing_address['addressLine'][1] : '';
$address['billing_city'] = ! empty( $billing_address['city'] ) ? $billing_address['city'] : '';
$address['billing_state'] = ! empty( $billing_address['region'] ) ? $this->convert_state_name_to_id( $billing_address['country'], $billing_address['region'] ) : '';
$address['billing_postcode'] = ! empty( $billing_address['postalCode'] ) ? $billing_address['postalCode'] : '';
$address['billing_company'] = '';
return $address;
}
/**
* Check if payment is pending.
*
* @param string $revolut_order_id Revolut order id.
*/
protected function is_pending_payment( $revolut_order_id ) {
$revolut_order = $this->api_client->get( '/orders/' . $revolut_order_id );
return ! isset( $revolut_order['state'] ) || ( isset( $revolut_order['state'] ) && 'PENDING' === $revolut_order['state'] );
}
/**
* Save or Update customer session temporarily.
*
* @param string $revolut_order_id Revolut order id.
*
* @throws Exception Exception.
*/
public function add_or_update_temp_session( $revolut_order_id ) {
$order_metadata['id_customer'] = get_current_user_id();
$order_metadata['cart'] = WC()->cart->get_cart_for_session();
$order_metadata['cart_totals'] = WC()->cart->get_totals();
$order_metadata['applied_coupons'] = WC()->cart->get_applied_coupons();
$order_metadata['coupon_discount_totals'] = WC()->cart->get_coupon_discount_totals();
$order_metadata['coupon_discount_tax_totals'] = WC()->cart->get_coupon_discount_tax_totals();
$order_metadata['get_removed_cart_contents'] = WC()->cart->get_removed_cart_contents();
$temp_session = wp_json_encode( $order_metadata );
global $wpdb;
$wpdb->query(
$wpdb->prepare(
'INSERT INTO ' . $wpdb->prefix . 'wc_revolut_temp_session (order_id, temp_session)
VALUES (%s, %s) ON DUPLICATE KEY UPDATE temp_session = VALUES(temp_session)',
array(
$revolut_order_id,
$temp_session,
)
)
); // db call ok; no-cache ok.
}
/**
* Get Revolut customer id.
*
* @param int $wc_customer_id WooCommerce customer id.
*/
public function get_revolut_customer_id( $wc_customer_id = false ) {
if ( ! $wc_customer_id ) {
$wc_customer_id = get_current_user_id();
}
if ( empty( $wc_customer_id ) ) {
return null;
}
global $wpdb;
$revolut_customer_id = $wpdb->get_col( $wpdb->prepare( 'SELECT revolut_customer_id FROM ' . $wpdb->prefix . 'wc_revolut_customer WHERE wc_customer_id=%s', array( $wc_customer_id ) ) ); // db call ok; no-cache ok.
$revolut_customer_id = reset( $revolut_customer_id );
if ( empty( $revolut_customer_id ) ) {
$revolut_customer_id = null;
}
$revolut_customer_id_with_mode = explode( '_', $revolut_customer_id );
if ( count( $revolut_customer_id_with_mode ) > 1 ) {
list( $api_mode, $revolut_customer_id ) = $revolut_customer_id_with_mode;
if ( $api_mode !== $this->api_client->mode ) {
$this->delete_customer_record( $wc_customer_id );
return null;
}
}
// verify customer id through api.
$revolut_customer = $this->api_client->get( '/customers/' . $revolut_customer_id );
if ( empty( $revolut_customer['id'] ) ) {
$this->delete_customer_record( $wc_customer_id );
return null;
}
return $revolut_customer_id;
}
/**
* Remove customer db record
*
* @param string $wc_customer_id customer id.
*/
public function delete_customer_record( $wc_customer_id ) {
global $wpdb;
$wpdb->delete( // phpcs:ignore
$wpdb->prefix . 'wc_revolut_customer',
array(
'wc_customer_id' => $wc_customer_id,
)
);
}
/**
* Update Revolut Order Total
*
* @param float $order_total Order total.
* @param string $currency Order currency.
* @param string $public_id Order public id.
*
* @return bool
* @throws Exception Exception.
*/
public function update_revolut_order_total( $order_total, $currency, $public_id ) {
$order_id = $this->get_revolut_order_by_public_id( $public_id );
$order_total = round( $order_total, 2 );
$revolut_order_total = $this->get_revolut_order_total( $order_total, $currency );
$body = array(
'amount' => $revolut_order_total,
'currency' => $currency,
);
if ( empty( $order_id ) ) {
return false;
}
$revolut_order = $this->api_client->get( "/orders/$order_id" );
if ( ! isset( $revolut_order['public_id'] ) || ! isset( $revolut_order['id'] ) || 'PENDING' !== $revolut_order['state'] ) {
return false;
}
$revolut_order = $this->api_client->patch( "/orders/$order_id", $body );
if ( ! isset( $revolut_order['public_id'] ) || ! isset( $revolut_order['id'] ) ) {
return false;
}
return true;
}
/**
* Fetch Revolut order by public id
*
* @param String $public_id Revolut public id.
*
* @return string|null
*/
public function get_revolut_order_by_public_id( $public_id ) {
global $wpdb;
// resolve into order_id.
return $this->uuid_dashes(
$wpdb->get_col( // phpcs:ignore
$wpdb->prepare(
'SELECT HEX(order_id) FROM ' . $wpdb->prefix . 'wc_revolut_orders
WHERE public_id=UNHEX(REPLACE(%s, "-", ""))',
array( $public_id )
)
)
);
}
/**
* Load Merchant Public Key from API.
*
* @return string
*/
public function get_merchant_public_api_key() {
try {
$merchant_public_key = $this->get_revolut_merchant_public_key();
if ( ! empty( $merchant_public_key ) ) {
return $merchant_public_key;
}
$merchant_public_key = $this->api_client->get( WC_GATEWAY_PUBLIC_KEY_ENDPOINT, true );
$merchant_public_key = isset( $merchant_public_key['public_key'] ) ? $merchant_public_key['public_key'] : '';
if ( empty( $merchant_public_key ) ) {
return '';
}
$this->set_revolut_merchant_public_key( $merchant_public_key );
return $merchant_public_key;
} catch ( Exception $e ) {
return '';
}
}
/**
* Check Merchant Account features.
*
* @return bool
*/
public function check_feature_support() {
try {
$this->api_client->set_public_key( $this->get_revolut_merchant_public_key() );
$merchant_features = $this->api_client->get( '/public/merchant', true );
return isset( $merchant_features['features'] ) && is_array( $merchant_features['features'] ) && in_array(
WC_GATEWAY_REVPAY_INDEX,
$merchant_features['features'],
true
);
} catch ( Exception $e ) {
return false;
}
}
/**
* Checks if page is pay for order and change subs payment page.
*
* @return bool
*/
public function is_subs_change_payment() {
return ( isset( $_GET['pay_for_order'] ) && isset( $_GET['change_payment_method'] ) ); // phpcs:ignore
}
/**
* Unset Revolut public_id
*/
protected function unset_revolut_public_id() {
WC()->session->__unset( "{$this->api_client->mode}_revolut_public_id" );
}
/**
* Unset Revolut public_id
*/
protected function unset_revolut_express_checkout_public_id() {
WC()->session->__unset( "{$this->api_client->mode}_revolut_express_checkout_public_id" );
}
/**
* Set Revolut public_id
*
* @param string $value Revolut public id.
*/
protected function set_revolut_public_id( $value ) {
WC()->session->set( "{$this->api_client->mode}_revolut_public_id", $value );
}
/**
* Set Revolut public_id
*
* @param string $value Revolut public id.
*/
public function set_revolut_express_checkout_public_id( $value ) {
WC()->session->set( "{$this->api_client->mode}_revolut_express_checkout_public_id", $value );
}
/**
* Get Revolut public_id
*
* @return array|string|null
*/
protected function get_revolut_public_id() {
$public_id = WC()->session->get( "{$this->api_client->mode}_revolut_public_id" );
if ( empty( $public_id ) ) {
return null;
}
$order_id = $this->get_revolut_order_by_public_id( $public_id );
if ( empty( $order_id ) ) {
return null;
}
return $public_id;
}
/**
* Get Revolut public_id
*
* @return array|string|null
*/
protected function get_revolut_express_checkout_public_id() {
return WC()->session->get( "{$this->api_client->mode}_revolut_express_checkout_public_id" );
}
/**
* Get Revolut Merchant Public Key
*
* @return array|string|null
*/
protected function get_revolut_merchant_public_key() {
return WC()->session->get( "{$this->api_client->mode}_revolut_merchant_public_key" );
}
/**
* Set Revolut Merchant Public Key
*
* @param string $value Revolut Merchant public Key.
*/
protected function set_revolut_merchant_public_key( $value ) {
WC()->session->set( "{$this->api_client->mode}_revolut_merchant_public_key", $value );
}
/**
* Replace dashes
*
* @param mixed $uuid uuid.
*
* @return string|string[]|null
*/
protected function uuid_dashes( $uuid ) {
if ( is_array( $uuid ) ) {
if ( isset( $uuid[0] ) ) {
$uuid = $uuid[0];
}
}
$result = preg_replace( '/(\w{8})(\w{4})(\w{4})(\w{4})(\w{12})/i', '$1-$2-$3-$4-$5', $uuid );
return $result;
}
/**
* Check if is not minor currency
*
* @param string $currency currency.
*
* @return bool
*/
public function is_zero_decimal( $currency ) {
return 'jpy' === strtolower( $currency );
}
/**
* Get order total for Api.
*
* @param float $order_total order total amount.
* @param string $currency currency.
*/
public function get_revolut_order_total( $order_total, $currency ) {
$order_total = round( (float) $order_total, 2 );
if ( ! $this->is_zero_decimal( $currency ) ) {
$order_total = round( $order_total * 100 );
}
return (int) $order_total;
}
/**
* Get order total for WC order.
*
* @param float $revolut_order_total order total amount.
* @param string $currency currency.
*/
public function get_wc_order_total( $revolut_order_total, $currency ) {
$order_total = $revolut_order_total;
if ( ! $this->is_zero_decimal( $currency ) ) {
$order_total = round( $order_total / 100, 2 );
}
return $order_total;
}
/**
* Get total amount value from Revolut order.
*
* @param array $revolut_order Revolut order.
*/
public function get_revolut_order_amount( $revolut_order ) {
return isset( $revolut_order['order_amount'] ) && isset( $revolut_order['order_amount']['value'] ) ? (int) $revolut_order['order_amount']['value'] : 0;
}
/**
* Get shipping amount value from Revolut order.
*
* @param array $revolut_order Revolut order.
*/
public function get_revolut_order_total_shipping( $revolut_order ) {
$shipping_total = isset( $revolut_order['delivery_method'] ) && isset( $revolut_order['delivery_method']['amount'] ) ? (int) $revolut_order['delivery_method']['amount'] : 0;
$currency = $this->get_revolut_order_currency( $revolut_order );
if ( $shipping_total ) {
return $this->get_wc_order_total( $shipping_total, $currency );
}
return 0;
}
/**
* Get currency from Revolut order.
*
* @param array $revolut_order Revolut order.
*/
public function get_revolut_order_currency( $revolut_order ) {
return isset( $revolut_order['order_amount'] ) && isset( $revolut_order['order_amount']['currency'] ) ? $revolut_order['order_amount']['currency'] : '';
}
/**
* Get total shipping price.
*/
public function get_cart_total_shipping() {
$cart_totals = WC()->session->get( 'cart_totals' );
$shipping_total = 0;
if ( ! empty( $cart_totals ) && is_array( $cart_totals ) && in_array( 'shipping_total', array_keys( $cart_totals ), true ) ) {
$shipping_total = $cart_totals['shipping_total'];
}
return $this->get_revolut_order_total( $shipping_total, get_woocommerce_currency() );
}
/**
* Check is data submitted for GET request.
*
* @param string $submit request key.
*/
public function check_is_get_data_submitted( $submit ) {
return isset( $_GET[ $submit ] ); // phpcs:ignore
}
/**
* Check is data submitted for POST request.
*
* @param string $submit request key.
*/
public function check_is_post_data_submitted( $submit ) {
return isset( $_POST[ $submit ] ); // phpcs:ignore
}
/**
* Safe get posted integer data
*
* @param string $post_key request key.
*/
public function get_posted_integer_data( $post_key ) {
if ( ! isset( $_POST[ $post_key ] ) ) { // phpcs:ignore
return 0;
}
return (int) $_POST[ $post_key ]; // phpcs:ignore
}
/**
* Safe get posted data
*
* @param string $post_key request key.
*/
public function get_post_request_data( $post_key ) {
if ( ! isset( $_POST[ $post_key ] ) ) { // phpcs:ignore
return null;
}
return $this->recursive_sanitize_text_field( $_POST[ $post_key ]); // phpcs:ignore
}
/**
* Safe get request data
*
* @param string $get_key request key.
*/
public function get_request_data( $get_key ) {
if ( ! isset( $_GET[ $get_key ] ) ) { // phpcs:ignore
return null;
}
return $this->recursive_sanitize_text_field( $_GET[ $get_key ] ); // phpcs:ignore
}
/**
* Clear data.
*
* @param mixed $var data for cleaning.
*/
public function recursive_sanitize_text_field( $var ) {
if ( is_array( $var ) ) {
return array_map( array( $this, 'recursive_sanitize_text_field' ), $var );
} else {
return sanitize_text_field( wp_unslash( $var ) );
}
}
/**
* Get two-digit language iso code.
*/
public function get_lang_iso_code() {
return substr( get_locale(), 0, 2 );
}
/**
* Check order status
*
* @param String $order_status data for checking.
*/
public function check_is_order_has_capture_status( $order_status ) {
if ( 'authorize' !== $this->api_settings->get_option( 'payment_action' ) ) {
return false;
}
if ( 'yes' !== $this->api_settings->get_option( 'accept_capture' ) ) {
return false;
}
$order_status = ( 0 !== strpos( $order_status, 'wc-' ) ) ? 'wc-' . $order_status : $order_status;
$selected_capture_status_list = $this->api_settings->get_option( 'selected_capture_status_list' );
$customize_capture_status = $this->api_settings->get_option( 'customise_capture_status' );
if ( empty( $selected_capture_status_list ) || 'no' === $customize_capture_status ) {
$selected_capture_status_list = array( 'wc-processing', 'wc-completed' );
}
return in_array( $order_status, $selected_capture_status_list, true );
}
/**
* Check order status
*
* @param String $public_id data.
*/
public function get_available_card_brands( $public_id ) {
try {
$order_details = $this->api_client->get( "/orders/token/{$public_id}", false, true );
if ( ! isset( $order_details['availableCardBrands'] ) || empty( $order_details['availableCardBrands'] ) ) {
return '';
}
return implode( ',', array_map( 'strtolower', $order_details['availableCardBrands'] ) );
} catch ( Exception $e ) {
$this->log_error( 'get_available_card_brands: ' . $e->getMessage() );
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* Logger trait
*
* Provides shared logic for logging errors
*
* @package WooCommerce
* @category Payment Gateways
* @author Revolut
* @since 2.0
*/
defined( 'ABSPATH' ) || exit();
if ( ! class_exists( 'WC_Logger' ) ) {
return;
}
/**
* WC_Revolut_Logger_Trait trait.
*/
trait WC_Revolut_Logger_Trait {
/**
* Logger status
*
* @var boolean
*/
protected $enable_logging = true;
/**
* Return error message
*
* @param String $message Log message.
*/
public function log_error( $message ) {
$logger = wc_get_logger();
$context = array( 'source' => 'revolut-gateway-for-woocommerce' );
if ( is_array( $message ) ) {
$message = wp_json_encode( $message );
}
$logger->error( $message, $context );
}
/**
* Return error message
*
* @param String $message Log message.
*/
public function log_info( $message ) {
$logger = wc_get_logger();
$context = array( 'source' => 'revolut-gateway-for-woocommerce' );
if ( is_array( $message ) ) {
$message = wp_json_encode( $message );
}
$logger->info( $message, $context );
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* Settings trait
*
* Provides shared logic for navigation tab settings
*
* @package WooCommerce
* @category Payment Gateways
* @author Revolut
* @since 2.0
*/
defined( 'ABSPATH' ) || exit();
/**
* WC_Revolut_Settings_Trait trait.
*/
trait WC_Revolut_Settings_Trait {
/**
* Tab title
*
* @var string
*/
protected $tab_title;
/**
* API settings
*
* @var WC_Revolut_Settings_API
*/
protected $api_settings;
/**
* Add setting tab to admin configuration.
*
* @param array $tabs setting tabs.
*/
public function admin_nav_tab( $tabs ) {
$tabs[ $this->id ] = $this->tab_title;
return $tabs;
}
/**
* Display navigation for settings page
*/
public function output_settings_nav() {
if ( $this->check_is_get_data_submitted( 'page' ) && $this->check_is_get_data_submitted( 'section' ) ) {
$is_revolut_section = 'wc-settings' === $this->get_request_data( 'page' ) && in_array( $this->get_request_data( 'section' ), WC_REVOLUT_GATEWAYS, true ) || $this->get_request_data( 'section' ) === 'revolut_advanced_settings';
if ( $is_revolut_section ) {
include REVOLUT_PATH . 'templates/html-settings-nav.php';
}
}
}
/**
* Check API mode
*/
public function is_sandbox() {
return 'sandbox' === $this->get_option( 'mode' );
}
}