JezK
Edit File: class-cartflows-pro-gateway-square-old.php
<?php /** * Square Credit Card Gateway. * * Remove this file after 2 updates. * * @package cartflows */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } use SquareConnect\Configuration; use Square\Models\CreatePaymentRequest; use SquareConnect\ApiClient; use SquareConnect\Api\PaymentsApi; use SquareConnect\Api\RefundsApi; use SquareConnect\Model\RefundPaymentRequest; /** * Class Cartflows_Pro_Gateway_Square_Old. */ class Cartflows_Pro_Gateway_Square_Old { /** * Member Variable * * @var instance */ private static $instance; /** * Key name variable * * @var key */ public $key = 'square_credit_card'; /** * Refund supported variable * * @var is_api_refund */ public $is_api_refund = true; /** * Initiator */ public static function get_instance() { if ( ! isset( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } /** * Constructor */ public function __construct() { add_filter( 'wc_' . $this->key . '_payment_form_tokenization_forced', array( $this, 'maybe_force_tokenization' ), 10, 2 ); add_filter( 'wc_payment_gateway_' . $this->key . '_process_payment', array( $this, 'create_token_process_payment' ), 10, 3 ); add_filter( 'wc_payment_gateway_' . $this->key . '_get_order', array( $this, 'square_get_order_to_add_token' ), 10, 2 ); add_action( 'cartflows_offer_child_order_created_' . $this->key, array( $this, 'store_square_meta_keys_for_refund' ), 10, 3 ); add_action( 'cartflows_offer_subscription_created', array( $this, 'add_subscription_payment_meta_for_square' ), 10, 3 ); add_action( 'cartflows_offer_accepted', array( $this, 'may_reduce_the_offer_product_stock' ), 10, 2 ); } /** * Forces tokenization for upsell/downsells. * * @since 1.5.0 * * @param bool $force_tokenization whether tokenization should be forced. * @return bool */ public function maybe_force_tokenization( $force_tokenization ) { wcf()->logger->log( 'Started: ' . __CLASS__ . '::' . __FUNCTION__ ); if ( isset( $_POST['post_data'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing $post_data = array(); $post_raw_data = sanitize_text_field( wp_unslash( $_POST['post_data'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Missing parse_str( $post_raw_data, $post_data ); $checkout_id = wcf_pro()->utils->get_checkout_id_from_data( $post_data ); $flow_id = wcf_pro()->utils->get_flow_id_from_data( $post_data ); if ( $checkout_id && $flow_id && wcf_pro()->flow->is_upsell_exist_in_flow( $flow_id, $checkout_id ) ) { $force_tokenization = true; wcf()->logger->log( 'Force save source enabled' ); } } wcf()->logger->log( $force_tokenization ); return $force_tokenization; } /** * Add token to order. * * @param object $order order data. * @param object $gateway class instance. */ public function square_get_order_to_add_token( $order, $gateway ) { if ( $this->key === $gateway->id ) { $this->set_square_gateway_config(); if ( empty( $order->payment->token ) ) { $order->payment->token = $order->get_meta( '_wc_square_credit_card_payment_token' ); } } return $order; } /** * Create token. * * @since 1.5.0 * * @param array $process_payment gateway data. * @param int $order_id order id. * @param object $gateway class instance. * @return array */ public function create_token_process_payment( $process_payment, $order_id, $gateway ) { $order = wc_get_order( $order_id ); if ( $this->key === $order->get_payment_method() ) { $this->set_square_gateway_config(); $order = $this->get_wc_gateway()->get_order( $order ); if ( empty( $order->payment->token ) && $order->get_customer_id() < 1 ) { try { $this->get_wc_gateway()->get_payment_tokens_handler()->create_token( $order ); } catch ( Exception $e ) { wcf()->logger->log( '\n ==== Exception Occured ==== \n Can not create the token.' ); } } } return $process_payment; } /** * Get WooCommerce payment geteways. * * @return array */ public function get_wc_gateway() { global $woocommerce; $gateways = $woocommerce->payment_gateways->payment_gateways(); return $gateways[ $this->key ]; } /** * After payment process. * * @param array $order order data. * @param array $product product data. * @return array */ public function process_offer_payment( $order, $product ) { $is_successful = false; // set up the square configuration. $this->set_square_gateway_config(); $fields = $this->prepare_order_data( $order, $product ); // API call for create payment. $payment_api = new PaymentsApi( $this->api_client ); $response = $payment_api->createPayment( $fields ); if ( empty( $response['error'] ) && isset( $response['payment'] ) ) { $payment_data = $response['payment']; $transaction_id = $payment_data['id']; $order_id = $order->get_id(); $order->update_status( 'processing' ); $this->store_offer_transaction( $order, $transaction_id, $product ); $is_successful = true; } else { wcf()->logger->log( '\n ==== Product Start ==== \n' . wcf_print_r( $product, true ) . '==== Product End ==== \n ==== Error Response start ==== \n' . wcf_print_r( $response, true ) . '==== Error Response end ====\n' ); } return $is_successful; } /** * Prepare data for payment. * * @param object $order order data. * @param array $product product data. * @return array */ public function prepare_order_data( $order, $product ) { $idempotency_key = strval( $order->get_id() . '_' . $product['step_id'] ); $location_id = $this->location_id; $currency = $order->get_currency(); $customer_id = $order->get_customer_id(); $_customer_user = $order->get_meta( '_customer_user' ); $customer_card_id = $order->get_meta( '_wc_square_credit_card_payment_token' ); $square_customer_id = $order->get_meta( '_wc_square_credit_card_customer_id' ); if ( empty( $square_customer_id ) ) { $square_customer_id = $order->get_meta( '_square_customer_id' ); } $shipping_address = array( 'address_line_1' => $order->get_shipping_address_1() ? $order->get_shipping_address_1() : $order->get_billing_address_1(), 'address_line_2' => $order->get_shipping_address_2() ? $order->get_shipping_address_2() : $order->get_billing_address_2(), 'locality' => $order->get_shipping_city() ? $order->get_shipping_city() : $order->get_billing_city(), 'administrative_district_level_1' => $order->get_shipping_state() ? $order->get_shipping_state() : $order->get_billing_state(), 'postal_code' => $order->get_shipping_postcode() ? $order->get_shipping_postcode() : $order->get_billing_postcode(), 'country' => $order->get_shipping_country() ? $order->get_shipping_country() : $order->get_billing_country(), ); $billing_address = array( 'address_line_1' => $order->get_billing_address_1(), 'address_line_2' => $order->get_billing_address_2(), 'locality' => $order->get_billing_city(), 'administrative_district_level_1' => $order->get_billing_state(), 'postal_code' => $order->get_billing_postcode(), 'country' => $order->get_billing_country() ? $order->get_billing_country() : $order->get_shipping_country(), ); $fields = array( 'idempotency_key' => $idempotency_key, 'location_id' => $location_id, 'amount_money' => array( 'amount' => (int) $this->format_amount( $product['total'], $currency ), 'currency' => $currency, ), 'source_id' => $customer_card_id, 'customer_id' => $square_customer_id, 'shipping_address' => $shipping_address, 'billing_address' => $billing_address, 'reference_id' => (string) $order->get_id(), /* translators: %1$s: site name, %2$s: order id, %3$s: step id */ 'note' => sprintf( __( '%1$s - Order %2$s_%3$s - One Click Payment', 'cartflows-pro' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $order->get_id(), $product['step_id'] ), ); return $fields; } /** * Process amount to be passed to Square payment API. * * @param int $total order total. * @param string $currency currancy. */ public function format_amount( $total, $currency = '' ) { if ( ! $currency ) { $currency = get_woocommerce_currency(); } switch ( strtoupper( $currency ) ) { // Zero decimal currencies. case 'BIF': case 'CLP': case 'DJF': case 'GNF': case 'JPY': case 'KMF': case 'KRW': case 'MGA': case 'PYG': case 'RWF': case 'VND': case 'VUV': case 'XAF': case 'XOF': case 'XPF': $total = absint( $total ); break; default: $total = round( $total, 2 ) * 100; // In cents. break; } return $total; } /** * Store Offer Trxn Charge. * * @param WC_Order $order The order that is being paid for. * @param Object $response The response that is send from the payment gateway. * @param array $product The product data. */ public function store_offer_transaction( $order, $response, $product ) { $order->update_meta_data( 'cartflows_offer_txn_resp_' . $product['step_id'], $response ); $order->save(); } /** * Set up the required configuration for payment. */ public function set_square_gateway_config() { // Set the access tokan. $this->access_token = $this->get_wc_gateway()->get_plugin()->get_settings_handler()->get_access_token(); $this->access_token = empty( $this->access_token ) ? $this->get_wc_gateway()->get_plugin()->get_settings_handler()->get_option( 'sandbox_token' ) : $this->access_token; // Set the location id. $this->location_id = $this->get_wc_gateway()->get_plugin()->get_settings_handler()->get_location_id(); // Set host. $this->api_config = new Configuration(); $this->api_config->setHost( 'https://connect.squareup.com' ); $mode = get_option( 'wc_square_settings' ); if ( 'yes' === $mode['enable_sandbox'] ) { $this->api_config->setHost( 'https://connect.squareupsandbox.com' ); } $this->api_config->setAccessToken( $this->access_token ); $this->api_client = new ApiClient( $this->api_config ); } /** * Save required meta keys to refund seperate order. * * @param object $parent_order Parent order Object. * @param object $child_order Child order Object. * @param string $transaction_id id. */ public function store_square_meta_keys_for_refund( $parent_order, $child_order, $transaction_id ) { if ( ! empty( $transaction_id ) ) { $child_order->update_meta_data( '_wc_square_credit_card_square_location_id', $parent_order->get_meta( '_wc_square_credit_card_square_location_id', true ) ); $child_order->update_meta_data( '_wc_square_credit_card_authorization_code', $transaction_id ); $child_order->update_meta_data( '_wc_square_credit_card_customer_id', $parent_order->get_meta( '_wc_square_credit_card_customer_id', true ) ); $child_order->update_meta_data( '_wc_square_credit_card_square_order_id', $transaction_id ); $child_order->update_meta_data( '_wc_square_credit_card_trans_id', $transaction_id ); $child_order->update_meta_data( '_wc_square_credit_card_charge_captured', 'yes' ); $child_order->save(); } } /** * Process offer refund * * @param object $order Order Object. * @param array $offer_data offer data. * * @return string/bool. */ public function process_offer_refund( $order, $offer_data ) { // set up the square configuration. $this->set_square_gateway_config(); $currancy = $order->get_currency(); $response_id = false; if ( ! is_null( $offer_data['refund_amount'] ) ) { $fields = array( 'idempotency_key' => strval( $offer_data['order_id'] ), 'amount_money' => array( 'amount' => (int) $this->format_amount( $offer_data['refund_amount'], $currancy ), 'currency' => $currancy, ), 'payment_id' => $offer_data['transaction_id'], 'reason' => $offer_data['refund_reason'], ); // API call for refund payment. $refund_api = new RefundsApi( $this->api_client ); $response = $refund_api->refundPayment( $fields ); if ( empty( $response['error'] ) && isset( $response['refund'] ) ) { $refund_data = $response['refund']; $response_id = $refund_data['id']; } } return $response_id; } /** * Allow gateways to declare whether they support offer refund * * @return bool */ public function is_api_refund() { return $this->is_api_refund; } /** * Setup the Payment data for Square's Automatic Subscription. * * @param WC_Subscription $subscription An instance of a subscription object. * @param object $order Object of order. * @param array $offer_product array of offer product. */ public function add_subscription_payment_meta_for_square( $subscription, $order, $offer_product ) { if ( 'square_credit_card' === $order->get_payment_method() ) { $subscription->update_meta_data( '_wc_square_credit_card_payment_token', $order->get_meta( '_wc_square_credit_card_payment_token', true ) ); $subscription->update_meta_data( '_wc_square_credit_card_customer_id', $order->get_meta( '_wc_square_credit_card_customer_id', true ) ); $subscription->save(); } } /** * Reduce the offer product stock. * * @param object $order Object of order. * @param array $offer_product array of offer product. */ public function may_reduce_the_offer_product_stock( $order, $offer_product ) { // Do not update the quantity if the page gateway is not the one which is required. if ( 'square_credit_card' !== $order->get_payment_method() ) { return; } $product = wc_get_product( $offer_product['id'] ); if ( ! wcf_pro()->utils->is_separate_offer_order() && $product->managing_stock() ) { $new_stock = wc_update_product_stock( $offer_product['id'], $offer_product['qty'], 'decrease' ); $changes[] = array( 'product' => $product, 'from' => $new_stock + intval( $offer_product['qty'] ), 'to' => $new_stock, ); wc_trigger_stock_change_notifications( $order, $changes ); } } } /** * Prepare if class 'Cartflows_Pro_Gateway_Square_Old' exist. * Kicking this off by calling 'get_instance()' method */ Cartflows_Pro_Gateway_Square_Old::get_instance();