<?php
/**
 * Plugin Name: CyberSource - WooCommerce Payment Gateway
 * Plugin URI: https://codecanyon.net/item/woocommerce-cybersource-payment-gateway/12199526
 * Description: This extension allows you to accept payments in WooCommerce via Secure Acceptance Hosted Checkout and Secure Acceptance Checkout API.
 * Version: 1.54.49
 * Author: RyanPlugins
 * Author URI:https://codecanyon.net/user/ryanplugins
 *
 * WC requires at least: 3.0
 * WC tested up to: 9.6.0
 *
 */

 if ( ! defined( 'ABSPATH' ) ) exit;
 
function woocommerce_api_cybersource_sawm_init(){

	//Support HPOS
	add_action( 'before_woocommerce_init', function() {
		if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
			\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
		}
	} );
	
	if(!class_exists('WC_Payment_Gateway')) return; 
	
	class WC_API_Cybersource_SAWM extends WC_Payment_Gateway_CC {

		public static $log_enabled = false;
    	public static $log = false;

    	protected $profile_id;
    	protected $access_key;
    	protected $secret_key;
    	protected $profile_id_sop;
    	protected $access_key_sop;
    	protected $secret_key_sop;
    	protected $merchant_id;
    	protected $transaction_key;
    	public $line_items;
    	public $round_line_taxamount;
    	public $round_line_unitprice;
    	public $round_total_amount;
    	public $wm_cb_url;
    	public $sop_cb_url;
    	public $trans_type_web_standard_create;
    	public $signed_field_names;
    	public $unsigned_field_names;
    	public $locale;
    	public $trans_type_sop;
    	public $mode;
    	public $trans_type_so;
    	public $enable_mdd_fields;
    	public $avs;
		public $enable_billing_mobile_phone;
		public $enable_auto_split_address;

		private $transaction_response_page_url;
		private $cb_api;
		private $transaction_type; 
		private $merchant_reference; 
		public 	$remove_mdd_field_names;
		private $hmac_sha256;
		private $debug;
		private $save_card;
		private $secured_message;
		public $processing_level;
		private $units_of_measurement;
		private $item_commodity_code;
		private $maskcvc;
		private $pl_cards;
		private $custom_thankyou;
		private $custom_error;
		private $custom_cancel;
		private $custom_decline;
		private $enable_signature;
		private $enable_shipping_fields;
		public $dont_send_billing_fields;
		private $msg;
		private $is_sandbox;
		private $trans_type_web_standard_update;
		private $cards;
		public $address_input_size;
		private $default_status;
	
		public function __construct(){	
			$this->id 			= 'cybsawm';
			$this->method_title = __( 'Cybersource', 'woocommerce' );
			$this->method_description = __( 'WooCommerce Cybersource Payment Integration', 'woocommerce' );
			
			$this->transaction_response_page_url = WC()->api_request_url( 'WC_API_Cybersource_SAWM' ); // http://my-store.com/?wc-api=WC_API_Cybersource_SAWM
			$this->has_fields 	= false; 

			// API Supports
	      $this->supports = array(
	          'products',
	          'default_credit_card_form',
	          'tokenization',
	          'pre-orders'
	      );

			$this->init_form_fields();
			$this->init_settings();

			$this->title 			= __( $this->settings[ 'title' ], 'woocommerce' );
			$this->description 		= __( $this->settings[ 'description' ], 'woocommerce' );
			$this->mode 			= $this->settings[ 'mode' ];
			self::$log_enabled    	= 'yes' === $this->settings[ 'debug' ];
            

			//Simple Order API
			$this->merchant_id 				= $this->settings[ 'merchant_id' ];
			

			//APIs & Integration.
			$this->cb_api 					= $this->settings[ 'cb_api' ];
			
			$this->signed_field_names 	= $this->settings[ 'signed_field_names' ];
			$this->unsigned_field_names = $this->settings[ 'unsigned_field_names' ];
			$this->locale 				= $this->settings[ 'locale' ];
			$this->transaction_type		= $this->settings[ 'transaction_type' ];
			$this->merchant_reference	= $this->settings[ 'merchant_reference' ]; 
			$this->line_items			= $this->settings[ 'line_items' ]; 
			$this->round_total_amount	= 'yes' ===  $this->settings[ 'round_total_amount' ];
			$this->round_line_taxamount	= 'yes' ===  $this->settings[ 'round_line_taxamount' ];
			$this->round_line_unitprice	= 'yes' ===  $this->settings[ 'round_line_unitprice' ];
			$this->enable_mdd_fields    = 'yes' ===  $this->settings[ 'enable_mdd_fields' ];
			$this->remove_mdd_field_names = $this->settings['remove_mdd_field_names'];
			$this->enable_billing_mobile_phone  = !empty($this->settings[ 'enable_billing_mobile_phone' ]) ? $this->settings[ 'enable_billing_mobile_phone' ] : 'no';
						
			$this->hmac_sha256			= 'sha256';		
			$this->debug          		= $this->settings[ 'debug'];
			$this->save_card			= 'yes' === $this->settings[ 'save_card' ];
			$this->avs 					= 'yes' === $this->settings[ 'avs' ];
			$this->secured_message		= 'yes' === $this->settings[ 'secured_message' ];	
			$this->processing_level     = $this->settings['processing_level'];
			$this->units_of_measurement = $this->settings['units_of_measurement'];
			$this->item_commodity_code  = $this->settings['item_commodity_code'];
			$this->maskcvc               = 'yes' === $this->settings['maskcvc'];
			$this->pl_cards             = !empty($this->settings[ 'pl_cards' ]) ? $this->settings[ 'pl_cards' ] : array();
			
			$this->custom_thankyou     	= !empty($this->settings['custom_thankyou']) ? $this->settings['custom_thankyou'] : '';
			$this->custom_error     	= !empty($this->settings['custom_error']) ? $this->settings['custom_error'] : '';
			$this->custom_cancel     	= !empty($this->settings['custom_cancel']) ? $this->settings['custom_cancel'] : '';
			$this->custom_decline     	= !empty($this->settings['custom_decline']) ? $this->settings['custom_decline'] : '';
			$this->enable_signature     = 'yes' === $this->settings['enable_signature'];
			$enable_shipping_fields     = !empty($this->settings['enable_shipping_fields']) ? $this->settings['enable_shipping_fields'] : "no";
			$this->enable_shipping_fields  = 'yes' === $enable_shipping_fields;
			$this->dont_send_billing_fields = 'yes' === $this->settings['dont_send_billing_fields'];
			$this->enable_auto_split_address = 'yes' === $this->settings['enable_auto_split_address'];
			
			$this->msg['message'] 	= '';
			$this->msg['class'] 	= '';
			
			if( $this->mode  == 'p' ){

				$this->wm_cb_url  = esc_url( 'https://secureacceptance.cybersource.com/pay' );
				$this->sop_cb_url = esc_url( 'https://secureacceptance.cybersource.com/silent/pay' );

				// WM Profile
				$this->profile_id   	= $this->settings[ 'profile_id' ];
				$this->access_key 		= $this->settings[ 'access_key' ];
				$this->secret_key 		= $this->settings[ 'secret_key' ];

				// SOP Profile
				$this->profile_id_sop   	= $this->settings[ 'profile_id_sop' ];
				$this->access_key_sop 		= $this->settings[ 'access_key_sop' ];
				$this->secret_key_sop 		= $this->settings[ 'secret_key_sop' ];

				//Simple Order API
				$this->transaction_key 			= $this->settings[ 'transaction_key' ];

				$this->is_sandbox 			= 0;	

			}else{
				
				$this->wm_cb_url = esc_url( 'https://testsecureacceptance.cybersource.com/pay' );
				$this->sop_cb_url = esc_url( 'https://testsecureacceptance.cybersource.com/silent/pay' );

				// WM Profile
				$this->profile_id  			= $this->settings[ 'profile_id_test' ];
				$this->access_key  			= $this->settings[ 'access_key_test' ];
				$this->secret_key  			= $this->settings[ 'secret_key_test' ];

				// SOP Profile
				$this->profile_id_sop  		= $this->settings[ 'profile_id_sop_test' ];
				$this->access_key_sop  		= $this->settings[ 'access_key_sop_test' ];
				$this->secret_key_sop  		= $this->settings[ 'secret_key_sop_test' ];

				//Simple Order API
				$this->transaction_key 		= $this->settings[ 'transaction_key_test' ];

				$this->is_sandbox 				= 1;	

			}

			if( $this->settings['transaction_type'] == 'authorization' ){
				if( $this->save_card === true ){
					$this->trans_type_web_standard_create 		= "authorization,create_payment_token";
					$this->trans_type_web_standard_update 		= "authorization,update_payment_token";	
				} else {
					$this->trans_type_web_standard_create 		= "authorization";
					$this->trans_type_web_standard_update 		= "authorization";
				}
				
				$this->trans_type_sop 						= "authorization"; // Processing On-Demand Transactions
				$this->trans_type_so 						= "authorization"; // Processing On-Demand Transactions


			} else {

				if( $this->save_card === true ){
					$this->trans_type_web_standard_create 		= "sale,create_payment_token";
					$this->trans_type_web_standard_update 		= "sale,update_payment_token";
				} else {
					$this->trans_type_web_standard_create 		= "sale";
					$this->trans_type_web_standard_update 		= "sale";
				}
				

				$this->trans_type_sop    					= "sale"; // Processing On-Demand Transactions
				$this->trans_type_so    					= "sale"; // Processing On-Demand Transactions
			}


			$this->cards 	= $this->settings[ 'cards' ];
			$this->address_input_size = ! empty($this->settings[ 'address_input_size' ]) ? $this->settings[ 'address_input_size' ] : '';
			
			$this->default_status = !empty($this->settings['default_status']) ? $this->settings['default_status'] : 'default';

			add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options' ) );
			add_action( 'woocommerce_receipt_' .  $this->id , array( $this, 'receipt_page'), 10, 1 );
			add_action( 'woocommerce_api_wc_api_cybersource_sawm' , array( $this, 'transaction_response' ) ); 
			//counter check if the payment success but status is pending
			add_action( 'woocommerce_order_status_completed', array( $this , 'cybersource_thankyou_processing_order_status' ), 10 ,1);

			$cybersource_section = ! empty( $_REQUEST['section'] ) ? $_REQUEST[ 'section' ] : '';
			if($cybersource_section == $this->id ){
				add_action( 'admin_enqueue_scripts', array( $this, 'admin_settings_js') ); 	
			}

			add_action( 'woocommerce_before_checkout_form', array( $this , 'woocommerce_before_checkout_form'),10 );
            
		}

		// Getter and setter methods for the property if needed
		public function setTransactionResponsePageUrl($url) {
			$this->transaction_response_page_url = $url;
		}

		public function setCbApi($cb_api){
			$this->cb_api = $cb_api;

		} 
	
		public function getTransactionResponsePageUrl() {
			return $this->transaction_response_page_url;
		}

		public function getCbApi(){
			return $this->cb_api;
		} 

		public function admin_settings_js(){
		wp_enqueue_script( 'cybsawm-admin-js', plugins_url( 'assets/js/admin-setting.js' , __FILE__ ));
		wp_add_inline_script( 'cybsawm-admin-js', 'jQuery(document).ready(function($) { 
			// Web/Mobile Profile Credentials Live Keys
			$( "#woocommerce_cybsawm_access_key" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_access_key" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			$( "#woocommerce_cybsawm_secret_key" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_secret_key" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			// Web/Mobile Profile Credentials SandBox Keys
			$( "#woocommerce_cybsawm_access_key_test" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_access_key_test" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			$( "#woocommerce_cybsawm_secret_key_test" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_secret_key_test" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			//SOP Profile Credentials Live keys

			$( "#woocommerce_cybsawm_access_key_sop" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_access_key_sop" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			$( "#woocommerce_cybsawm_secret_key_sop" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_secret_key_sop" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			//SOP Profile Credentials Test keys
			$( "#woocommerce_cybsawm_access_key_sop_test" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_access_key_sop_test" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			$( "#woocommerce_cybsawm_secret_key_sop_test" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});
			$( "#woocommerce_cybsawm_secret_key_sop_test" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			//Simple Order API Credentials

			$( "#woocommerce_cybsawm_transaction_key" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});

			$( "#woocommerce_cybsawm_transaction_key" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

			$( "#woocommerce_cybsawm_transaction_key_test" ).focusin(function() {
				if($(this).attr("type") == "password"){ $(this).attr("type", "text");}else{$(this).attr("type", "password");}
			});

			$( "#woocommerce_cybsawm_transaction_key_test" ).focusout(function() {
				if($(this).attr("type") == "text"){ $(this).attr("type", "password");}else{$(this).attr("type", "text");}
			});

		 });' );
	}
		
		public function init_form_fields(){
			$signed_field_names = array(
				'access_key' 			=> 'access_key',
				'profile_id' 			=> 'profile_id',
				'transaction_uuid' 		=> 'transaction_uuid',
				'signed_field_names' 	=> 'signed_field_names',
				'unsigned_field_names' 	=> 'unsigned_field_names',
				'signed_date_time' 		=> 'signed_date_time',
				'locale' 				=> 'locale',
				'transaction_type' 		=> 'transaction_type',
				'reference_number' 		=> 'reference_number',
				'amount' 				=> 'amount',
				'currency' 				=> 'currency',
				'bill_city'				=> 'bill_city',
				'bill_to_address_city'	=> 'bill_to_address_city',
				'bill_to_address_country'	=> 'bill_to_address_country',
				'bill_address1'			=> 'bill_address1',
				'bill_to_address_line1'	=> 'bill_to_address_line1',
				'bill_to_address_line2'	=> 'bill_to_address_line2',
				'bill_to_address_postal_code'=> 'bill_to_address_postal_code',
				'bill_to_address_state'	=> 'bill_to_address_state',
				'bill_to_company_name'	=> 'bill_to_company_name' ,
				'bill_to_email'			=> 'bill_to_email' ,
				'bill_to_forename'		=> 'bill_to_forename',
				'bill_to_phone'			=> 'bill_to_phone',
				'bill_to_surname'		=> 'bill_to_surname',
				
				'ship_to_address_city'		=> 'ship_to_address_city',
				'ship_to_address_country'	=> 'ship_to_address_country',
				'ship_to_address_line1'		=> 'ship_to_address_line1',
				'ship_to_address_line2'		=> 'ship_to_address_line2',
				'ship_to_address_postal_code'	=> 'ship_to_address_postal_code',
				'ship_to_address_state'			=> 'ship_to_address_state',
				'ship_to_forename'				=> 'ship_to_forename',
				'ship_to_phone'					=> 'ship_to_phone',
				'ship_to_surname'				=> 'ship_to_surname',
				'customer_ip_address'   => 'customer_ip_address',
				'consumer_id'			=> 'consumer_id',
				'payment_token'			=> 'payment_token',
				'tax_amount'			=> 'tax_amount',
				'card_type'				=> 'card_type',
				'card_number'			=> 'card_number',
				'card_expiry_date'		=> 'card_expiry_date',
				'card_cvn'				=> 'card_cvn',
				'payment_method'		=> 'payment_method',
				'merchant_id'			=> 'merchant_id',
				'device_fingerprint_id' => 'device_fingerprint_id',
				'payer_authentication_mobile_phone' => 'payer_authentication_mobile_phone',
				'customer_browser_screen_height' => 'customer_browser_screen_height',
				'customer_browser_screen_width' => 'customer_browser_screen_width',
				'duty_amount'				=> 'duty_amount',
				'discount_amount'			=> 'discount_amount',
				'purchasing_level' 			=> 'purchasing_level',
				'ship_from_postal_code'     => 'ship_from_postal_code',				
				'user_po'					=> 'user_po',

			);

			$signed_field_names_default  = array(
				'access_key' 			=> 'access_key',
				'profile_id' 			=> 'profile_id',
				'transaction_uuid' 		=> 'transaction_uuid',
				'signed_field_names' 	=> 'signed_field_names',
				'unsigned_field_names' 	=> 'unsigned_field_names',
				'signed_date_time' 		=> 'signed_date_time',
				'locale' 				=> 'locale',
				'transaction_type' 		=> 'transaction_type',
				'reference_number' 		=> 'reference_number',
				'amount' 				=> 'amount',
				'currency' 				=> 'currency',
				'bill_to_address_city'	=> 'bill_to_address_city',
				'bill_to_address_country'	=> 'bill_to_address_country',
				'bill_to_address_line1'	=> 'bill_to_address_line1',
				'bill_to_address_line2'	=> 'bill_to_address_line2',
				'bill_to_address_postal_code'=> 'bill_to_address_postal_code',
				'bill_to_address_state'	=> 'bill_to_address_state',
				'bill_to_company_name'	=> 'bill_to_company_name' ,
				'bill_to_email'			=> 'bill_to_email' ,
				'bill_to_forename'		=> 'bill_to_forename',
				'bill_to_phone'			=> 'bill_to_phone',
				'bill_to_surname'		=> 'bill_to_surname',
				'ship_to_address_city'		=> 'ship_to_address_city',
				'ship_to_address_country'	=> 'ship_to_address_country',
				'ship_to_address_line1'		=> 'ship_to_address_line1',
				'ship_to_address_line2'		=> 'ship_to_address_line2',
				'ship_to_address_postal_code'	=> 'ship_to_address_postal_code',
				'ship_to_address_state'			=> 'ship_to_address_state',
				'ship_to_forename'				=> 'ship_to_forename',
				'ship_to_phone'					=> 'ship_to_phone',
				'ship_to_surname'				=> 'ship_to_surname',
				'customer_ip_address'   => 'customer_ip_address',
				'payment_token'			=> 'payment_token',
				'tax_amount'			=> 'tax_amount',
				'merchant_id'			=> 'merchant_id',
				'device_fingerprint_id' => 'device_fingerprint_id',
				'payer_authentication_mobile_phone' => 'payer_authentication_mobile_phone',				
				'customer_browser_screen_height' => 'customer_browser_screen_height',
				'customer_browser_screen_width' => 'customer_browser_screen_width',
			);

			//* WP Custom Page List

			$pages = get_pages(); 

			$page_list = array();

			if( !empty($pages)){				

				$page_list[''] = __( 'Default' );     

				foreach ( $pages as $page ) {
					$page_list[$page->ID] = __( $page->post_title );        
				}


			}

			$this->form_fields = array(
                    'enabled' 			=> array(
	                    'title' 		=> __( 'Enable/Disable', 'woocommerce' ),
	                    'type' 			=> 'checkbox',
	                    'label' 		=> __( 'Enable CyberSource - WooCommerce Payment Gateway.', 'woocommerce' ),
	                    'default' 		=> 'no'
	                    ),
	                'title' => array(
	                    'title' 		=> __( 'Title:', 'woocommerce' ),
	                    'type'			=> 'text',
	                    'description' 	=> __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
	                    'default' 		=> __( 'CyberSource Secure Acceptance', 'woocommerce' )
	                    ),
	                'description' => array(
	                    'title' 		=> __( 'Description:', 'woocommerce' ),
	                    'type' 			=> 'textarea',
	                    'description' 	=> __( 'This controls the description which the user sees during checkout.', 'woocommerce' ),
	                    'default' 		=> __( 'Pay via CyberSource Secure Acceptance.', 'woocommerce' )
	                    ),

	                'mode' 	=> array(
	                    'title' 		=> __( 'Environment', 'woocommerce' ),
	                    'type' 			=> 'select',
	                    'description' 	=> '',
	       				'options'     	=> array(
	                    	's' 	=> __( 'Sandbox', 'woocommerce' ),
					        'p'		=> __( 'Production', 'woocommerce' )
							)
						),

	                'cb_api' => array(
		                 'title'       => __( 'Integration', 'woocommerce' ),
		                 'type'        => 'select',
		                 'description' => __( 'Choose Secure Acceptance APIs & Integration.', 'woocommerce' ),
		                 'default'     => 'sawm',
		                 'options'     => array(
		                     'sawm'  	=> __( 'Hosted Checkout (Web/Mobile)', 'woocommerce' ),
		                     'sasop' 	=> __( 'Checkout API (SOP)', 'woocommerce' ),
		                     //'so' 	 	=> __( 'SOAP Toolkit API', 'woocommerce' ),
		                     'sawmsop'  => __( 'Web/Mobile & Silent Order POST (OLD Integration)', 'woocommerce' )
		                 )
		             ),

	                'merchant_id' => array(
	                    'title' 		=> __( 'Merchant ID', 'woocommerce' ),
	                    'type' 			=> 'text',
	                    'description' 	=> __( 'Your Cybersource Merchant ID.', 'woocommerce' ),
	                    'desc_tip'      => true,
	                ),

	                //Cybersource Secure Acceptance Web/Mobile Profile Credentials
	                'wm_header' => array(
						'title'       => __( 'Hosted Checkout (Web/Mobile) Profile Credentials', 'woocommerce' ),
						'type'        => 'header',
						'description' => __( 'Enter your cybersource hosted checkout web/mobile profile secure acceptance credentials.', 'woocommerce' ),
						'desc_tip'          => false,
					),
	                'profile_id' => array(
	                    'title' 		=> __( 'PROFILE ID (live)', 'woocommerce' ),
	                    'type' 			=> 'text',
	                    'description' 	=> __( 'Your Hosted Checkout PROFILE ID.', 'woocommerce' ),
	                    ),
					
					'access_key' => array(
	                    'title' 		=> __( 'ACCESS KEY (live)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your Hosted Checkout ACCESS KEY.', 'woocommerce' )
	                    ),  	
					
					'secret_key' => array(
	                    'title' 		=> __( 'SECRET KEY (live)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your Hosted Checkout SECRET KEY.', 'woocommerce' )
	                    ),

					'wm_hr' => array(
						'title'       => '',
						'type'        => 'hr',
						'description' => '',
						'desc_tip'    => false,
					),

					'profile_id_test' => array(
	                    'title' 		=> __( 'PROFILE ID (test)', 'woocommerce' ),
	                    'type' 			=> 'text',
	                    'description' 	=> __( 'Your Test Hosted Checkout PROFILE ID.', 'woocommerce' )
	                    ),
					
					'access_key_test' => array(
	                    'title' 		=> __( 'ACCESS KEY (test)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your Test Hosted Checkout ACCESS KEY.', 'woocommerce' )
	                    ),  	
					
					'secret_key_test' => array(
	                    'title' 		=> __( 'SECRET KEY (test)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your Test Hosted Checkout SECRET KEY.', 'woocommerce' )
	                    ),

					//'Cybersource Secure Acceptance SOP Profile Credentials

					'sop_header' => array(
						'title'       => __( 'Checkout API (SOP) Profile Credentials', 'woocommerce' ),
						'type'        => 'header',
						'description' => __( 'Enter your cybersource checkout (sop) profile secure acceptance credentials.', 'woocommerce' ),
						'desc_tip'          => false,
					),

					'profile_id_sop' => array(
	                    'title' 		=> __( 'PROFILE ID (live)', 'woocommerce' ),
	                    'type' 			=> 'text',
	                    'description' 	=> __( 'Your checkout api PROFILE ID.', 'woocommerce' )
	                    ),
					
					'access_key_sop' => array(
	                    'title' 		=> __( 'ACCESS KEY (live)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your checkout api ACCESS KEY.', 'woocommerce' )
	                    ),  	
					
					'secret_key_sop' => array(
	                    'title' 		=> __( 'SECRET KEY (live)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your checkout api SECRET KEY.', 'woocommerce' )
	                    ),	

	                 'sop_hr' => array(
						'title'       => '',
						'type'        => 'hr',
						'description' => '',
						'desc_tip'    => false,
					),   	

	                 'profile_id_sop_test' => array(
	                    'title' 		=> __( 'PROFILE ID (test)', 'woocommerce' ),
	                    'type' 			=> 'text',
	                    'description' 	=> __( 'Your checkout api PROFILE ID.', 'woocommerce' )
	                    ),
					
					'access_key_sop_test' => array(
	                    'title' 		=> __( 'ACCESS KEY (test)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your checkout api ACCESS KEY.', 'woocommerce' )
	                    ),  	
					
					'secret_key_sop_test' => array(
	                    'title' 		=> __( 'SECRET KEY (test)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'Your checkout api SECRET KEY.', 'woocommerce' )
	                    ),	

					//Cybersource Simple Order API Credentials
					'so_header' => array(
						'title'       => __( 'SOAP Toolkit API Credentials', 'woocommerce' ),
						'type'        => 'header',
						'description' => __( 'Enter your cybersource soap toolkit api credentials.', 'woocommerce' ),
						'desc_tip'          => false,
					),
					
					'transaction_key' => array(
	                    'title' 		=> __( 'Transaction Key (Live)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'In the navigation pane of the Business Center, click Account Management > Transaction Security Keys > Security Keys for the SOAP Toolkit API.', 'woocommerce' ),
	                    ),

					'transaction_key_test' => array(
	                    'title' 		=> __( 'Transaction Key (test)', 'woocommerce' ),
	                    'type' 			=> 'password',
	                    'description' 	=> __( 'In the navigation pane of the Test Business Center, click Account Management > Transaction Security Keys > Security Keys for the SOAP Toolkit API.', 'woocommerce' ),
	                    ),

					'processing_level' => array(
						'title'       => __( 'Level  Processing', 'woocommerce' ),
						'description' => __( 'Enable Processing Level II and III', 'woocommerce' ),
						'default'     => 'no',
						'desc_tip'    => false,
						'type'        => 'select',
		                'default'     => 'none',
		                'options'     => array(
		                	 'none'  	=> __( 'Please select level', 'woocommerce' ),
		                     '2'  	=> __( 'Level 2', 'woocommerce' ),
		                     '3' 	=> __( 'Level 3', 'woocommerce' )
		                 )
					),

					'units_of_measurement' => array(
						'title'       => __( 'Units of Measurement', 'woocommerce' ),
						'description' => __( 'Unit of measure, or unit of measure code, for the item.', 'woocommerce' ),
						'desc_tip'    => false,
						'type'        => 'text',
					),

					'item_commodity_code' => array(
						'title'       => __( 'Item Commodity Code', 'woocommerce' ),
						'description' => __( 'International description code used to classify the item.', 'woocommerce' ),
						'desc_tip'    => false,
						'type'        => 'text',
					),
					'pl_cards' => array(
						'title'             => __( 'Card Types can process Level', 'woocommerce' ),
						'type'              => 'multiselect',
						'class'             => 'wc-enhanced-select',
						'css'               => 'width: 450px;',
						'default'           => array( 
														'1'
													 ) ,
						'description'       => __( 'Set Accepted Card Logos.', 'woocommerce' ),
						'options'           => array( 
														'1' => 'visa', 
														'2' => 'mastercard', 
														'3' => 'amex',
														
												),
						'desc_tip'          => true,
						'custom_attributes' => array(
							'data-placeholder' => __( 'Set Card Types can process Level', 'woocommerce' )
						)
					),

					'gen_hr' => array(
						'title'       => '',
						'type'        => 'hr',
						'description' => '',
						'desc_tip'    => false,
					),  

					'signed_field_names' => array(
						'title'             => __( 'Signed Field Names', 'woocommerce' ),
						'type'              => 'multiselect',
						'class'             => 'wc-enhanced-select',
						'css'               => 'width: 450px;',
						'default'           => $signed_field_names_default,
						'description'       => __( 'Set Signed Field Names.', 'woocommerce' ),
						'options'           => $signed_field_names,
						'desc_tip'          => true,
						'custom_attributes' => array(
							'data-placeholder' => __( 'Set Signed Field Names', 'woocommerce' )
						)
					),
					
					'unsigned_field_names' => array(
						'title'             => __( 'Unsigned Field Names', 'woocommerce' ),
						'type'              => 'multiselect',
						'class'             => 'wc-enhanced-select',
						'css'               => 'width: 450px;',
						'default'           => '',
						'description'       => __( 'Unsigned Field Names.', 'woocommerce' ),
						'options'           => $signed_field_names,
						'desc_tip'          => true,
						'custom_attributes' => array(
							'data-placeholder' => __( 'Unsigned Field Names', 'woocommerce' )
						)
					),

					'save_card' => array(
						'title'             => __( 'Save Card', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable Save Card', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => true,
						'description'       =>  __( 'If this enabled the card token will automatically save to the database.', 'woocommerce' ) ,
					),
					
					'line_items' => array(
						'title'             => __( 'Offer-Line Details', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable Offer-Line Details', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => true,
						'description'       =>  __( 'Cybersource Offer-Line Details [ item_#_name,  item_#_code, item_#_quantity, item_#_sku,item_#_unit_price, item_#_unit_price, item_#_tax_amount ] ', 'woocommerce' ) ,
					),

					'enable_mdd_fields' => array(
						'title'             => __( 'Enable MDD Fields', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Cybersource Merchant Defined Data Fields (MDD).', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'remove_mdd_field_names' => array(
						'title'             => __( 'Remove MDD Field Name', 'woocommerce' ),
						'type'              => 'multiselect',
						'class'             => 'wc-enhanced-select',
						'css'               => 'width: 450px;',
						'default'           => '',
						'description'       => __( 'You can remove the following MDD Field Names.', 'woocommerce' ),
						'options'           => array(
							"merchant_defined_data1" => "merchant_defined_data1",
							"merchant_defined_data2" => "merchant_defined_data2",
							"merchant_defined_data3" => "merchant_defined_data3",
							"merchant_defined_data4" => "merchant_defined_data4",
							"merchant_defined_data5" => "merchant_defined_data5",
							"merchant_defined_data6" => "merchant_defined_data6",
							"merchant_defined_data7" => "merchant_defined_data7",
							"merchant_defined_data8" => "merchant_defined_data8",
							"merchant_defined_data9" => "merchant_defined_data9",
							"merchant_defined_data10" => "merchant_defined_data10",
							"merchant_defined_data11" => "merchant_defined_data11",
							"merchant_defined_data12" => "merchant_defined_data12",
							"merchant_defined_data13" => "merchant_defined_data13",
							"merchant_defined_data14" => "merchant_defined_data14",
							"merchant_defined_data15" => "merchant_defined_data15",
							"merchant_defined_data16" => "merchant_defined_data16",
							"merchant_defined_data17" => "merchant_defined_data17",
							"merchant_defined_data18" => "merchant_defined_data18",
							"merchant_defined_data19" => "merchant_defined_data19",
							"merchant_defined_data20" => "merchant_defined_data20",
						),
						'desc_tip'          => true,
						'custom_attributes' => array(
							'data-placeholder' => __( 'Remove MDD Field Names', 'woocommerce' )
						)
					),

					'enable_billing_mobile_phone' => array(
						'title'             => __( 'Enable Mobile Phone', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Cybersource Enable Mobile Phone for Payer Authentication Enrollment', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'enable_auto_split_address' => array(
						'title'             => __( 'Enable Auto Split Address', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable Auto Split Address ( Billing and Shipping )', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'enable_shipping_fields' => array(
						'title'             => __( 'Shipping Fields Override', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Cybersource Enable Shipping Fields Override. <a href="'.esc_url( admin_url() . "?page=cybersource-fields" ).'"> Edit here</a>', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'dont_send_billing_fields' => array(
						'title'             => __( 'Dont Send Billing Fields', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Cybersource Dont Sent Billing Fields - Hosted Checkout only.', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'round_total_amount' => array(
						'title'             => __( 'Rounding Off Total Amount', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable Rounding Off Total Amount', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'round_line_taxamount' => array(
						'title'             => __( 'Rounding Off Line Tax Amount', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable Rounding Off Line Tax Amount', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),
					

					'round_line_unitprice' => array(
						'title'             => __( 'Rounding Off Line Unit Price', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable Rounding Off Line Unit Price', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'avs' => array(
						'title'             => __( 'Address Verification Service (AVS)', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Disable Simple Order (SOAP) API Address Verification Service (AVS)', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'maskcvc' => array(
						'title'             => __( 'Mask Card code', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable masking Card code(CVC)', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'secured_message' => array(
						'title'             => __( 'Secure Error Message', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable secure customer error message', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					
					'transaction_type' => array(
		                 'title'       => __( 'Transaction Type Default', 'woocommerce' ),
		                 'type'        => 'select',
		                 'description' => __( 'Choose Transaction Type.', 'woocommerce' ),
		                 'default'     => 'sale',
		                 'desc_tip'    => true,
		                 'options'     => array(
		                     
							 'authorization' => __( 'Authorization', 'woocommerce' ),
		                     'sale' => __( 'Sale', 'woocommerce' )


		                 )
		             ),
					 
	                'locale' => array(
		                 'title'       => __( 'Localization', 'woocommerce' ),
		                 'type'        => 'select',
		                 'description' => __( 'Choose local language on Secure Acceptance.', 'woocommerce' ),
		                 'default'     => 'en-us',
		                 'desc_tip'    => true,
		                 'options'     => array(
		                     'ar-xn' => __( 'Arabic', 'woocommerce' ),
		                     'km-kh' => __( 'Cambodia', 'woocommerce' ),
							 'km-kh' => __( 'Cambodia', 'woocommerce' ),
							 'zh-hk' => __( 'Chinese—Hong Kong', 'woocommerce' ),
							 'zh-mo' => __( 'Chinese—Maco', 'woocommerce' ),
							 'zh-cn' => __( 'Chinese—Mainland', 'woocommerce' ),
							 'zh-sg' => __( 'Chinese—Singapore', 'woocommerce' ),
							 'zh-tw' => __( 'Chinese—Taiwan', 'woocommerce' ),
							 'cz-cz' => __( 'Czech', 'woocommerce' ),
							 'nl-nl' => __( 'Dutch', 'woocommerce' ),
							 'en-us' => __( 'English—American ', 'woocommerce' ),
							 'en-gb' => __( 'English—Britain ', 'woocommerce' ),
							 'en-ca' => __( 'English—Canada', 'woocommerce' ),
							 'en-ie' => __( 'English—Ireland ', 'woocommerce' ),
							 'en-nz' => __( 'English—New Zealand', 'woocommerce' ),
							 'fr-fr' => __( 'French', 'woocommerce' ),
							 'fr-ca' => __( 'French—Canada', 'woocommerce' ),
							 'de-de' => __( 'German', 'woocommerce' ),
							 'de-at' => __( 'German—Austria', 'woocommerce' ),
							 'hu-hu' => __( 'Hungary', 'woocommerce' ),
							 'id-id' => __( 'Indonesian', 'woocommerce' ),
							 'it-it' => __( 'Italian', 'woocommerce' ),
							 'ja-jp' => __( 'Japanese', 'woocommerce' ),
							 'ko-kr' => __( 'Korean', 'woocommerce' ),
							 'lo-la' => __( 'Lao People’s Democratic Republic', 'woocommerce' ),
							 'ms-my' => __( 'Malaysian Bahasa', 'woocommerce' ),
							 'tl-ph' => __( 'Philippines Tagalog', 'woocommerce' ),
							 'pl-pl' => __( 'Polish', 'woocommerce' ),
							 'pt-br' => __( 'Portuguese—Brazil', 'woocommerce' ),
							 'ru-ru' => __( 'Russian', 'woocommerce' ),
							 'sk-sk' => __( 'Slovakian', 'woocommerce' ),
							 'es-es' => __( 'Spanish', 'woocommerce' ),
							 'es-ar' => __( 'Spanish—Argentina', 'woocommerce' ),
							 'es-cl' => __( 'Spanish—Chile', 'woocommerce' ),
							 'es-co' => __( 'Spanish—Colombia', 'woocommerce' ),
							 'es-mx' => __( 'Spanish—Mexico', 'woocommerce' ),
							 'es-pe' => __( 'Spanish—Peru', 'woocommerce' ),
							 'es-us' => __( 'Spanish—American', 'woocommerce' ),
							 'th-th' => __( 'Thai', 'woocommerce' ),
							 'tr-tr' => __( 'Turkish', 'woocommerce' ),
							 'vi-vn' => __( 'Vietnamese', 'woocommerce' ),
		                 )
		             ),

	                'address_input_size' => array(
	                    'title' 		=> __( 'Address 1 & 2 Maximum Character Length', 'woocommerce' ),
	                    'type' 			=> 'text',
	                    'description' 	=> __( 'Your Billing Address 1 & 2 Maximum Character Length.', 'woocommerce' )
	                    ),

					 'merchant_reference' => array(
							'title' 		=> __( 'Merchant Reference Prefix', 'woocommerce' ),
							'type' 			=> 'text',
							'description' 	=> __( 'Your Cybersource Merchant Reference Prefix. eg. MYSTORENAME #{ORDERNO}', 'woocommerce' ),
							'default' 		=> __(  "#{ORDERNO}"." ". get_bloginfo() , 'woocommerce' ),
							'desc_tip'      => true,
	                    ),
                   
					'cards' => array(
						'title'             => __( 'Accepted Card Logos', 'woocommerce' ),
						'type'              => 'multiselect',
						'class'             => 'wc-enhanced-select',
						'css'               => 'width: 450px;',
						'default'           => array( 
														'visa' => 'visa' ,
													  	'mastercard' => 'mastercard', 
													  	'discover' => 'discover', 
													  	'amex' => 'amex',
													  	'jcb' => 'jcb' ) ,
						'description'       => __( 'Set Accepted Card Logos.', 'woocommerce' ),
						'options'           => array( 
														'visa' => 'visa', 
														'mastercard' => 'mastercard', 
														'discover' => 'discover', 
														'amex' => 'amex',
														'jcb' => 'jcb',
														'diners' => 'diners',
														'laser' => 'laser',
														'maestro' => 'maestro'
												),
						'desc_tip'          => true,
						'custom_attributes' => array(
							'data-placeholder' => __( 'Set Accepted Card Logos', 'woocommerce' )
						)
					),

					'custom_thankyou' => array(
						'title'       => __( 'Thank You Page', 'woocommerce' ),
						'type'        => 'select',
						'description' => __( 'Custom Thank you Page.', 'woocommerce' ),
						'default'     => '',        
						'options'     => $page_list
					),
				
					'custom_error' => array(
						'title'       => __( 'Error Page', 'woocommerce' ),
						'type'        => 'select',
						'description' => __( 'You can put this shortcode <strong>[cybersource_error_page_message]</strong> in your custom page so that you can display the gateway error', 'woocommerce' ),
						'default'     => '',        
						'options'     => $page_list
					),
				
					'custom_cancel' => array(
						'title'       => __( 'Cancel Page', 'woocommerce' ),
						'type'        => 'select',
						'description' => __( 'Custom Cancel Page.', 'woocommerce' ),
						'default'     => '',        
						'options'     => $page_list
					),

					'custom_decline' => array(
						'title'       => __( 'Decline Page', 'woocommerce' ),
						'type'        => 'select',
						'description' => __( 'You can put this shortcode <strong>[cybersource_error_page_message]</strong> in your custom page so that you can display the gateway error.', 'woocommerce' ),
						'default'     => '',        
						'options'     => $page_list
					),

					'default_status' => array(
						'title'       => esc_html__( 'Default Order Status', 'woocommerce' ),
						'type'        => 'select',
						'description' => esc_html__( 'Choose order status.', 'woocommerce' ),
						'default'     => 'default',
						'desc_tip'    => true,
						'options'     => array(
						  'default'			=> esc_html__( 'Default', 'woocommerce' ),
						  'on-hold'         => esc_html__( 'On Hold', 'woocommerce' ),
						  'processing' 		=> esc_html__( 'Processing', 'woocommerce' ),
						  'pending' 		=> esc_html__( 'Pending Payment', 'woocommerce' ),
						  'completed' 		=> esc_html__( 'Completed ', 'woocommerce' )
						)
					),

					'enable_signature' => array(
						'title'             => __( 'Enable Signature Verification', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Cybersource signature verification request/response data validator', 'woocommerce' ),
						'default'           => 'no',
						'desc_tip'          => false
					),

					'debug' => array(
						'title'             => __( 'Logs', 'woocommerce' ),
						'type'              => 'checkbox',
						'label'             => __( 'Enable logging', 'woocommerce' ),
						'default'           => 'no',
						'description'       =>  sprintf( __( 'Log %s events, such as API requests, inside <code>%s</code>', 'woocommerce' ), $this->method_title, wc_get_log_file_path( $this->id ) ),
					)
			);	
	
		}
		
		
		public function process_payment( $order_id ){
			global $woocommerce;

			//$order	= new WC_Order( $order_id );
			$order = wc_get_order( $order_id );

			$date_completed = $order->get_date_completed();
			$status = $order->get_status();

			if(!empty($date_completed) && $status == 'completed'){

				$duplicate_order_number = array(
					'order_id' => $order_id,
					'status' => $order->get_status(),
					'date_completed' => $order->get_date_completed(),
					'old_billing_email' => $order->get_billing_email(),
					'new_billing_email' => wc_clean($_REQUEST['billing_email']),
				);

				parent::log( 'Cybersource Request - Duplicate Order number: ' . print_r( $duplicate_order_number, true ) );

				wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Sorry something went wrong on your order, Please contact the support!" ) , 'woocommerce'), "error" );
				return false;

			}

			if( ! empty( $_POST['_cb_card_token'] ) ){
				$cb_card_token = wc_clean( $_POST['_cb_card_token'] );

				// if ( ! add_post_meta(  $order_id , '_cb_card_token' , wc_clean( $cb_card_token ) , true ) ) {
				// 	update_post_meta ( $order_id, '_cb_card_token' , wc_clean( $cb_card_token ) );
				// }

				$order->update_meta_data( '_cb_card_token', wc_clean( $cb_card_token )  );
				$order->save();

			} else {
				// if ( ! add_post_meta(  $order_id , '_cb_card_token' , 'new' , true ) ) {
				// 	update_post_meta ( $order_id, '_cb_card_token' , 'new' );
				// }

				$order->update_meta_data( '_cb_card_token', 'new'  );
				$order->save();

			}

			// create transaction UUID

			$cb_uuid = uniqid() . '-' . $order_id;
			//$cb_uuid = uniqid()  . $order_id;
			// if ( ! add_post_meta(  $order_id , '_cb_transaction_uuid' , $cb_uuid , true ) ) {
			// 		update_post_meta ( $order_id, '_cb_transaction_uuid' , $cb_uuid );
			// }

			$order->update_meta_data( '_cb_transaction_uuid', $cb_uuid  );
			$order->save();

			$confirm_save_card = ! empty($_POST[ 'confirm_save_card' ] ) ?  wp_kses_post( $_POST[ 'confirm_save_card' ]) : '';


			if( $_POST['_cb_card_token'] == 'new' && ! empty($confirm_save_card )){
				// if ( ! add_post_meta(  $order_id , '_confirm_save_card' , $confirm_save_card , true ) ) {
				// 		update_post_meta ( $order_id, '_confirm_save_card' , $confirm_save_card );
				// }

				$order->update_meta_data( '_confirm_save_card', $confirm_save_card   );
				$order->save();

			}

			if($this->dont_send_billing_fields === false ){

				$this->cybersource_custom_validate_address_fields();

				$addres_max_length = ! empty($this->address_input_size) ? $this->address_input_size : '41';

				// Billing Address Fields Validate

				if(! empty($order->get_billing_address_1()) && strlen($order->get_billing_address_1()) >= $addres_max_length ){
					wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Billing Address 1 Maximum Character Length Exceeded!" ) , 'woocommerce'), "error" );
					return false;
				}

				if(! empty($order->get_billing_address_2()) && strlen($order->get_billing_address_2()) >= $addres_max_length ){
					wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Billing Address 2 Maximum Character Length Exceeded!" ) , 'woocommerce'), "error" );
					return false;
				}

				
				// Shipping Address Fields Validate

				$addres_max_length = ! empty($this->address_input_size) ? $this->address_input_size : 41;

				if(! empty($order->get_shipping_address_1()) && strlen($order->get_shipping_address_1()) >= $addres_max_length ){
						wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Shipping Address 1 Maximum Character Length Exceeded!" ) , 'woocommerce'), "error" );
						return false;
				}

				if(! empty($order->get_shipping_address_2()) && strlen($order->get_shipping_address_2()) >= $addres_max_length ){
					wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Shipping Address 2 Maximum Character Length Exceeded!" ) , 'woocommerce'), "error" );
					return false;
				}		


			}
			
			
			$checkout_url_args = array( 'order-pay' => $order_id, 'key' => $order->get_order_key() );
			$checkout_url = add_query_arg( $checkout_url_args, wc_get_checkout_url());

			if(  $order_id > 0 ){

				return array(
					'result' => 'success',
					'redirect' => esc_url_raw($checkout_url)
				);

			} else {

				wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Order ID!" ) , 'woocommerce'), "error" );
				return false;

			}


			
		}
		
		public function receipt_page( $order_id ){

			global $woocommerce;

			wp_enqueue_style( 'wc-cybersource-receipt-css', plugins_url( 'assets/css/wc-cybersource-receipt.min.css' , __FILE__ )  ); 
	    	wp_enqueue_script( 'wc-cybersource-jquery-js', "https://code.jquery.com/jquery-3.6.0.min.js" , 'jquery' );
			wp_enqueue_script( 'wc-cybersource-jquery-block-js', "https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" , 'jquery' );
			wp_enqueue_script( 'wc-cybersource-receipt-js', plugins_url( 'assets/js/wc-cybersource-receipt.min.js' , __FILE__ ) , 'jquery' ); 
			
			$order = wc_get_order( $order_id );

			// MDD Fields ( Merchant Custom Fields)	
			if( $this->enable_mdd_fields === true ){
				$mdd_fields = apply_filters( 'cybersource_add_signed_field_names', $order_id );

				// remove the mdd field before submit

				if( is_array( $this->remove_mdd_field_names ) && !empty($this->remove_mdd_field_names)){

					foreach ($this->remove_mdd_field_names as $k => $v ){
						unset($mdd_fields[$v]);
					}
				}

			} else {
				$mdd_fields = array();
			}
			
			if( ! empty ( $this->signed_field_names ) ) {
				if( is_array(  $mdd_fields ) && ! empty( $mdd_fields ) ){
					$signed_field_names = array_merge( $this->signed_field_names, array_keys( $mdd_fields ) );
					$signed_field_names = implode(',', $signed_field_names);	
				} else {
					$signed_field_names = implode(',', $this->signed_field_names);		
				}

			} else{
				$signed_field_names = "";
			}

			if( ! empty( $this->unsigned_field_names ) ){
				$unsigned_field_names = implode(',', $this->unsigned_field_names);	
			} else {
				$unsigned_field_names = "";
			}
			
			if ( ! empty( $this->merchant_reference ) ){
				$reference = str_replace( '{ORDERNO}', $order->get_order_number() , $this->merchant_reference );
			}else{
				$reference = sprintf( __( '%s - Order %s', 'woocommerce' ), esc_html( get_bloginfo() ), $order->get_order_number() );
			}
			
			$amount = $order->get_total();
			$currency = get_woocommerce_currency();

            // check amount if <= 0 
			if($amount == "" ){
				$order->add_order_note( sprintf( "Transaction Error: '%s'","Zero Amount Generated" ) );
				wc_add_notice( __( sprintf( "%s","Something went wrong. Please try again." ) , 'woocommerce'), "error" );
				wp_redirect( wc_get_checkout_url() ); exit;		
			}
			
			$card_token = get_post_meta( $order_id , '_cb_card_token', true );
			
			// Offer-Line Details
			if( $this->line_items == 'yes' ){

				$cart_items = $woocommerce->cart->get_cart();
				// (e) clear 

				$cb_sf_line_times = array();
				if( ! empty( $cart_items ) ){
					$x = 0;
					foreach( $cart_items  as $values ){
						
						if( $values[ 'product_id' ] ){
							$product = wc_get_product( $values['product_id']);
							$product_sku  = $product->get_sku();
							$products_cats = $product->get_category_ids();
						} else {
							$product = wc_get_product( $values['variation_id']);
							$product_sku = $product->get_sku();
							$products_cats = $product->get_category_ids();
						}

						
						if( ! empty( $product_sku ) ){
							$sku = $product_sku;
						} else {
							$sku = "EMPTY";
						}
						
						
						if( $this->round_line_taxamount === false ){
							$line_tax_amount = (double) number_format($values['line_tax'], 2, ".", "");	
						} else {
							$line_tax_amount = round( $values['line_tax'] );	
							
						}

						if ( $this->round_line_unitprice === false ) {
							$line_unit_price =  (double) number_format($values['line_total'], 2, ".", "");
						} else {
							$line_unit_price = round($values['line_total']);
						}
						

						$_product = wc_get_product( $values['product_id'] );
					    $cb_sf_line_times['item_'.$x.'_name'] 		= sanitize_text_field($_product->get_name());
						$cb_sf_line_times['item_'.$x.'_code'] 		= $values['product_id'];
						$cb_sf_line_times['item_'.$x.'_quantity'] 	= $values['quantity'];
						$cb_sf_line_times['item_'.$x.'_sku'] 		=  $sku;
						$cb_sf_line_times['item_'.$x.'_unit_price'] = $line_unit_price;
						$cb_sf_line_times['item_'.$x.'_tax_amount'] = $line_tax_amount;
						$cb_sf_line_times['line_item_count'] 		= count($cart_items);

						$x++;
					}
				}
			}
			

			if( $card_token == 'new' ){
			    
				$profile_id = $this->profile_id;
				$access_key = $this->access_key;
				$secret_key = $this->secret_key;
				$cb_action_url = $this->wm_cb_url;
				$transaction_type  = $this->trans_type_web_standard_create;

				// if ( ! add_post_meta(  $order_id , '_cb_integration' , 'sawm' , true ) ) {
				// 	update_post_meta ( $order_id, '_cb_integration' , 'sawm' );					
				// } 

				$order->update_meta_data( '_cb_integration', 'sawm' );
				$order->save();
				
				$payment_token = "";
				
				$signed_field_names = explode( ',', $signed_field_names );
				$key = array_search( 'payment_token' , $signed_field_names);

				if (false !== $key) {
					unset($signed_field_names[$key]);
				}
				
				if($this->line_items == 'yes'){
					$signed_field_names = array_merge( array_keys($cb_sf_line_times), $signed_field_names ) ;
					$signed_field_names = implode(',',$signed_field_names);		
				} else {
				    $signed_field_names = implode(',',$signed_field_names);		
				}

				if( wp_is_mobile() ){
					$thank_you_redirecting_message = __( 'Please wait...', 'woocommerce' );	
				} else {
					$thank_you_redirecting_message = __( 'Thank you for your order. We are now redirecting you to CyberSource Secure Acceptance payment page. Please wait...' , 'woocommerce' );	
				}

				

			} else {

				$profile_id = $this->profile_id_sop;
				$access_key = $this->access_key_sop;
				$secret_key = $this->secret_key_sop;
				$cb_action_url 		= $this->sop_cb_url;
				$transaction_type  	= $this->trans_type_sop;
				$payment_token 		= base64_decode($card_token);
				
				// if ( ! add_post_meta(  $order_id , '_cb_integration' , 'sasop' , true ) ) {
				// 	update_post_meta ( $order_id, '_cb_integration' , 'sasop' );
				// } 
				
				$order->update_meta_data( '_cb_integration', 'sasop' );
				$order->save();
				
				if($this->line_items == 'yes'){
					$signed_field_names = explode( ',', $signed_field_names );
					$signed_field_names = array_merge( array_keys($cb_sf_line_times), $signed_field_names ) ;
					$signed_field_names = implode(',',$signed_field_names);		
				}
				
				if( wp_is_mobile() ){
					$thank_you_redirecting_message = __( 'Please wait...', 'woocommerce' );	
				} else {
					$thank_you_redirecting_message = __( 'Thank you for your order! Your purchase is being processed. Please wait...' , 'woocommerce' );          
				}
				

			}
			
			if( $this->round_total_amount === false ){
				$amount = (double) number_format($amount, 2, ".", "");
			} else {
				$amount = round($amount);
			} 

			if( $this->round_line_taxamount === false ){
				$tax_amount = (double) number_format($order->get_total_tax(), 2, ".", "");	
			} else {
				$tax_amount = round( $order->get_total_tax() );	
				
			}
			
			//$cb_uuid = get_post_meta( $order_id , '_cb_transaction_uuid', true );
			$cb_uuid = $order->get_meta( '_cb_transaction_uuid' );
			?>
		
			<form id="cb_payment_confirmation" action="<?php echo esc_url($cb_action_url);?>" method="POST" >
			<?php
			// Fingerprinting text input    
			do_action( 'cybersource_device_fingerprint_profiler' );	

			$consumer_id = $order->get_customer_id();

			if( empty($consumer_id) || $consumer_id == 0 ){
				$consumer_id = $order_id.time();
			} 

			// controlling billing address not send to cybersource

			if($this->dont_send_billing_fields === true ){
				$get_billing_city = "";
				$get_billing_country = "";
				$get_billing_address_1 = "";
				$get_billing_address_2 = "";
				$get_billing_postcode = "";
				$get_billing_state = "";

			} else {
				$get_billing_city = sanitize_text_field($this->strip_extra_char($order->get_billing_city()));
				$get_billing_country = sanitize_text_field($order->get_billing_country());
				$get_billing_address_1 = sanitize_text_field($this->strip_extra_char($order->get_billing_address_1()));
				$get_billing_address_2 = sanitize_text_field($this->strip_extra_char($order->get_billing_address_2()));
				$get_billing_postcode = sanitize_text_field($order->get_billing_postcode());
				$get_billing_state = sanitize_text_field($order->get_billing_state());
			}

			if( strtolower($this->enable_billing_mobile_phone) == 'yes' ){
				$payer_authentication_mobile_phone = $order->get_meta('billing_mobile_phone');
			} else {
				$payer_authentication_mobile_phone = $order->get_billing_phone();
			}

			$payer_authentication_mobile_phone = str_replace("+","",sanitize_text_field($payer_authentication_mobile_phone));
			$payer_authentication_mobile_phone = str_replace(" ","",sanitize_text_field($payer_authentication_mobile_phone));

			// sanitize phone number
			$bill_to_phone = str_replace("+","",sanitize_text_field($order->get_billing_phone()));
			$bill_to_phone = str_replace(" ","",sanitize_text_field($bill_to_phone));

			$ship_to_phone					= str_replace("+","",sanitize_text_field($order->get_billing_phone()));
			$ship_to_phone					= str_replace(" ","",$ship_to_phone);

			$cb_args = array(
				  'transaction_uuid' 		=> sanitize_text_field($cb_uuid),
				  'signed_date_time' 		=> gmdate("Y-m-d\TH:i:s\Z") ,
				  'access_key' 				=> sanitize_text_field($access_key),
				  'profile_id' 				=> sanitize_text_field($profile_id),
				  'signed_field_names' 		=> $signed_field_names,
				  'unsigned_field_names'	=> $unsigned_field_names ,
				  'locale' 					=> $this->locale,
				  'transaction_type' 		=> sanitize_text_field($transaction_type) ,
				  'reference_number' 		=> $order->get_order_number() ,
				  'amount' 					=> $amount,
				  'tax_amount'				=> $tax_amount,	
				  'currency' 				=> $currency,
				  'bill_city'				=> $get_billing_city,
				  'bill_to_address_city'	=> $get_billing_city,
				  'bill_to_address_country'	=> $get_billing_country,
				  'bill_address1'			=> $get_billing_address_1,
				  'bill_to_address_line1'	=> $get_billing_address_1,
				  'bill_to_address_line2'	=> $get_billing_address_2,
				  'bill_to_address_postal_code'=> $get_billing_postcode,
				  'bill_to_address_state'	=> $get_billing_state,
				  'bill_to_company_name'	=> sanitize_text_field($this->strip_extra_char(substr($order->get_billing_company(),0,40))),
				  'bill_to_email'			=> sanitize_text_field($order->get_billing_email()) ,
				  'bill_to_forename'		=> sanitize_text_field($this->strip_extra_char($order->get_billing_first_name())),
				  'bill_to_phone'			=> $bill_to_phone,
				  'bill_to_surname'			=> sanitize_text_field($this->strip_extra_char($order->get_billing_last_name())),
				  'ship_to_address_city'	=> sanitize_text_field($this->strip_extra_char($order->get_shipping_city())),
				  'ship_to_address_country'	=> sanitize_text_field($order->get_shipping_country()),
				  'ship_to_address_line1'	=> sanitize_text_field($this->strip_extra_char($order->get_shipping_address_1())),
				  'ship_to_address_line2'	=> sanitize_text_field($this->strip_extra_char($order->get_shipping_address_2())),
				  'ship_to_address_postal_code'	=> sanitize_text_field($order->get_shipping_postcode()),
				  'ship_to_address_state'	=> sanitize_text_field($order->get_shipping_state()),
				  'ship_to_phone'			=> $ship_to_phone,
				  'ship_to_forename'		=> sanitize_text_field($this->strip_extra_char($order->get_shipping_first_name())),
				  'ship_to_surname'			=> sanitize_text_field($this->strip_extra_char($order->get_shipping_last_name())),
				  'consumer_id'				=> sanitize_text_field($consumer_id),
				  'merchant_id'				=> sanitize_text_field($this->merchant_id),
				  'customer_ip_address'		=> WC_Geolocation::get_ip_address(),
				  'device_fingerprint_id'   => apply_filters( 'cybersource_session_id', false ),
				  'payer_authentication_mobile_phone' => $payer_authentication_mobile_phone,
				  'customer_browser_screen_height' => sanitize_text_field($order->get_meta('billing_browser_screen_height')),
				  'customer_browser_screen_width' => sanitize_text_field($order->get_meta('billing_browser_screen_width')),
				  
				 	
		  );
		  
		  //Unset Payment fields
		  if( $this->enable_mdd_fields === true ){
			$cb_args = apply_filters( 'cybersource_unset_field_names', $cb_args );
		  }

		  if( $this->line_items == 'yes' ){
		  	$cb_args = array_merge( $cb_args, $cb_sf_line_times );
		  }	

		  if( is_array(  $mdd_fields ) && ! empty( $mdd_fields ) ){
		  		$cb_args = array_merge( $cb_args, $mdd_fields );
		  }
		  
		  if( ! empty($payment_token) ){
				$token         	=  $payment_token;
				$payment_token 	= array( 'payment_token' => $token );
				$cb_args 		= array_merge( $cb_args, $payment_token );
		  }
		
		$cb_signature = array( 'signature' => $this->sign( $cb_args , $secret_key ) );
		$cb_combined_params =  array_merge( $cb_args, $cb_signature);
           
		self::log( 'Cybersource Request: ' . print_r( $cb_combined_params, true ) );
		
		$cb_args_array = array();
		foreach($cb_combined_params as $key => $value){
			$cb_args_array[] = '<input type="hidden" name="'.esc_attr($key).'" value="'.sanitize_text_field($value).'" />';
		}		 
		
		echo implode('', $cb_args_array); ?>
		
		<input type="submit" class="button-alt" id="submit_cb_payment_form" value="<?php echo esc_attr( __( 'Pay via CyberSource Secure Acceptance', 'woocommece'));?>" /> 
		<a class="button-alt" href="<?php echo esc_url($order->get_cancel_order_url()); ?>"><?php echo __('Cancel order', 'woocommece');?></a>
        </form>
		<?php 
			
		}	

		public function admin_options(){

			global $woocommerce;

			$tab = 'checkout';

			if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
				$tab = 'advanced';
    		} 
		
			if ( $this->mode == 'p' && is_ssl() === false && get_option('woocommerce_force_ssl_checkout') == 'no' && $this->enabled == 'yes' ) : ?>
				<div class="inline error">
					<p>
						<?php _e( sprintf(__('%s Sandbox testing is disabled and can perform live transactions but the <a href="%s">force SSL option</a> is disabled; your checkout is not secure! Please enable SSL and ensure your server has a valid SSL certificate.', 'woocommerce'), $this->method_title, admin_url('admin.php?page=wc-settings&tab=' . $tab )), 'woocommerce' ); ?>
					</p>
				</div>
			<?php endif; ?>
			<h3><?php _e(  $this->method_title .' - WooCommerce Payment Gateway', 'woocommerce' ); ?></h3>
			<?php
			 echo __( sprintf('Learn how to setup <a href="%s" target="_blank">CyberSource Payment Gateway</a>', "https://ryanplugins.wordpress.com/2023/10/16/how-to-install-cybersource-payment-gateway-plugin/"), 'woocommerce' );
			
			?>
			
			
			<table class="form-table"><?php
			// Generate the HTML For the settings form.
			$this->generate_settings_html();
			?>
			</table>
			<!--/.form-table-->
			<?php 
				
		}
		
		public function payment_fields()
		{
			if ( $this->mode == 's' ){
				echo '<p>';
					echo esc_html__( 'TEST MODE/SANDBOX ENABLED', 'woocommerce' );
					echo '<br>';
					echo esc_html__( 'Secure Acceptance Web/Mobile & Silent Order POST', 'woocommerce' );
					echo '<br>';
					echo '<br>';
					echo  esc_html__( 'Test Cards:', 'woocommerce' );
					echo '<br>';
					echo  esc_html__( 'MasterCard: 5555 5555 5555 4444', 'woocommerce' );
					echo '<br>';
					echo  esc_html__( 'VISA: 4111 1111 1111 1111', 'woocommerce' );
					echo '<br>';echo '<br>';
				echo '<p>';
			}

			if( $this->description ){
				echo wp_kses_post( wpautop( wptexturize( $this->description ) ) );
			}

			$customer_id = get_current_user_id();
			if( $customer_id > 0 ){

				$customer_tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), $this->id );
				
				if( ! empty($customer_tokens)){

					echo __( '', 'woocommerce' );
					echo "<ul class='woocommerce-cb-ul'>";

					if( $this->save_card ) {

						foreach ( $customer_tokens as $c_token ) {

	                        $key 				= $c_token->get_id();
							$credit_card_number = $c_token->get_last4();
							$payment_token 		= $c_token->get_token();
							$exp_date           = $c_token->get_expiry_month() . '/'. substr($c_token->get_expiry_year() , -2 );
							$exp_date 			= sprintf("(expires %s)", $exp_date);
							$card_type          = $c_token->get_card_type();
							$is_default         = $c_token->get_is_default() == 1 ? 'checked':'';

							if($card_type  == 'echeck' ){
								$exp_date   = "";	
							}
					
							echo '<li><input data-index-id="'.base64_encode($key).'" type="radio" class="_cb_card_token" name="_cb_card_token" value="'.base64_encode($payment_token).'" '.$is_default.'> <strong>'.__( sprintf( "%s ending in %s %s", $card_type , $credit_card_number, $exp_date  ),'woocommerce' ).'</strong> <a href="javacript:;" class="woccommerce-cb-dashicons-dismiss" data-index-id="'.base64_encode($payment_token).'" data-card-token="'.base64_encode($payment_token).'"> <span class="dashicons dashicons-dismiss" style="text-decoration:none;display:none"></span></a></li>';
							
						}

						$display_new_card ="block";
						} else {
							$display_new_card ="none";
						}

					echo '<li style="display:'.$display_new_card.'"><input type="radio" class="_cb_card_token" name="_cb_card_token" value="new"> <strong>'.__( 'Use a new card' ,'woocommerce' ).'</strong>
							<br> <input type="checkbox" name="confirm_save_card" id="confirm_save_card" style="margin-left:15px;" /> '. __( 'Securely Save Card to Account', 'woocommerce' ) .'</li>';

						echo "</ul>";
				}

			}  else {
				echo '<input type="hidden" class="_cb_card_token" name="_cb_card_token" value="new"><input type="checkbox" name="confirm_save_card" id="confirm_save_card" style="margin-left:10px;"  /> '. __( 'Securely Save Card to Account', 'woocommerce' ) ;
			}
			
		}
	
		public function showMessage( $content )
		{
			$html  = '';
			$html .= '<div class="box '.$this->msg['class'].'-box">';
			$html .= $this->msg['message'];
			$html .= '</div>';
			$html .= $content;
				
			return $html;
				
		}
	
		
		public function sign ($params,$secret_key) {
		  return $this->signData( $this->buildDataToSign($params), $secret_key );
		}

		public function signData($data, $secretKey) {
			return base64_encode(hash_hmac('sha256', $data, $secretKey, true));
		}

		public function buildDataToSign($params) {
			$signedFieldNames = explode(",",$params["signed_field_names"]);
			
			foreach ($signedFieldNames as $field) {
			   $dataToSign[] = $field . "=" . $params[$field];
			}
			
			return $this->commaSeparate($dataToSign);
		}

		public function commaSeparate ($dataToSign) {
			return implode(",",$dataToSign);
		}

		public function cybersource_thankyou_processing_order_status( $order_id ){

			//$order = new WC_Order( $order_id );
			$order = wc_get_order( $order_id );
			$order_data = $order->get_data();

			$transaction_id = get_post_meta( $order_id, '_cyber_transaction_id' , true );
			$decision_id = get_post_meta( $order_id, '_cyber_decision_id',  true );

			$order_status = $this->virtual_order_payment_complete_order_status( $order->get_id() );

			// some paid transaction not change the order status 'processing'
			if ( 'pending' == $order_data['status'] && $decision_id == 'ACCEPT' && ! empty($transaction_id) ) {
				
				if($order_status == 'completed' ){
				    $order->update_status( 'completed' );
            	} else {
            		$order->update_status( 'processing' );
            	}	
			}
		}
		
		public function transaction_response(){
		
			@ob_clean();
			
			global $woocommerce;

			$headers = getallheaders();

			self::log( 'Cybersource Headers: ' . print_r( $headers, true ) );

			$request = ! empty( $_REQUEST ) ? $_REQUEST : false;
			
			if( $request ) { 				
			
				self::log( 'Cybersource Response: ' . print_r( $request, true ) );

				$reason_code 	= wc_clean ( $request[ 'reason_code' ] );
				$req_card_type 	= wc_clean ( $request[ 'req_card_type' ] );
				$req_currency 	= wc_clean ( $request[ 'req_currency' ] );
				$req_reference_number 	= wc_clean ( $request[ 'req_reference_number' ] );
				$decision 			= wc_clean ( $request[ 'decision' ] );
				$message 			= wc_clean ( __( $request[ 'message' ] , 'woocommerce' ) );
				$req_amount 		= wc_clean ( $request[ 'req_amount' ] );
				$req_payment_method = wc_clean ( $request[ 'req_payment_method' ] );
				$transaction_id 	= wc_clean ( $request[ 'transaction_id' ] );
				$transaction_uuid   = wc_clean ( $request[ 'req_transaction_uuid' ] );
				$request_token 		= wc_clean ( $request[ 'request_token' ] );
				$mnp			    = !empty($request[ 'mnp' ]) ? $request[ 'mnp' ] : '';				


				if( ! empty($request[ 'req_card_number' ])){
					$req_card_number = wc_clean ( $request[ 'req_card_number' ]);	
				} else {
					$req_card_number = wc_clean ( $request[ 'req_echeck_account_number' ]);	
				}

				if( ! empty( $request[ 'payment_token' ] )){
					$request_token   = wc_clean ( $request[ 'payment_token' ]);
				}

				if( ! empty($request[ 'req_card_type' ])){
					$req_card_type   = wc_clean ( $request[ 'req_card_type' ]);
				} else {
					$req_card_type   = wc_clean ( $request[ 'req_payment_method' ]);
				}

				if( ! empty($request[ 'req_card_expiry_date' ])){
					$req_card_expiry_date   = wc_clean ( $request[ 'req_card_expiry_date' ]);
				} else{
					$req_card_expiry_date   = 'NA';
				}
				

				if( ! empty($request[ 'score_card_account_type' ])){
					$req_score_card_account_type   = wc_clean ( $request[ 'score_card_account_type' ]);
				} else{
					$req_score_card_account_type   = $this->get_card_types(wc_clean ( $request[ 'req_card_type' ]));
				}

				//ACCEPT - Successful transaction. Reason codes 100 and 110
				//DECLINE - Transaction was declined. See reason codes 102, 200, 202, 203, 204, 205, 207, 208, 210, 211, 221, 222, 230, 231, 232, 233, 234, 236, 240, 475, 476, and 481.
				//REVIEW - Authorization was declined; however, the capture may still be possible. Review payment details. See reason codes 200, 201, 230, and 520
				//ERROR - Access denied, page not found, or internal server error. See reason codes 102, 104, and 150.
				//CANCEL - The customer did not accept the service fee conditions., The customer cancelled the transaction.  

				$cb_order_id  = explode( '-', $transaction_uuid);
				
				if( ! empty($cb_order_id[1])){
					$order_id = $cb_order_id[1];
				} else{
					//$order->add_order_note( sprintf( "%s Payments Failed: '%s'", $this->method_title, "Transaction UUID  Not Recognized!", $reason_code ) ); 
					if( $mnp == false ){
						self::log( sprintf( "Transaction Error: '%s'", "Transaction UUID  Not Recognized!" ) . " " . print_r( $request, true ) );
						wp_safe_redirect( wc_get_checkout_url() );
					}
					exit; 
				}

				// validate the reason code
				// 100 == success , 480 in review

				$allowed_codes = array( "100","480" );

				if( !in_array($reason_code,$allowed_codes) ){

					self::log( "Transaction Error Reason Code: ".$reason_code. " " . print_r( $request, true ) );
					wp_safe_redirect( add_query_arg( 'error', "declined", wc_get_checkout_url() ) );
					exit;	
					
				} 
				
				//$order 			= new WC_Order( $order_id );
				$order 			= wc_get_order( $order_id );
				$order_data 	= $order->get_data();
				$customer_id 	= $order->get_user_id();
				$date_completed = $order->get_date_completed();
				$o_status 		= $order->get_status();

				

				//order_id validation

				$original_order_id_email    = $order_data['billing']['email'];
				$cybersource_order_id_email = $request['req_bill_to_email'];

				if( !empty($date_completed) && $o_status == 'completed' ){

					// Possibly order id duplicate or glitch in the server.

					$cybersource_order_info = array(

						'cybersource_transaction_id' 	   =>  $request['transaction_id'],
						'cybersource_transaction_order_id' =>  $request['req_reference_number'],
						'cybersource_transaction_amount'   =>  $request['auth_amount'],
						'cybersource_transaction_forename' =>  $request['req_bill_to_forename'],
						'cybersource_transaction_surname'  =>  $request['req_bill_to_surname'],
						'cybersource_transaction_email'    =>  $request['req_bill_to_email'],
						'cybersource_transaction_id' 	   =>  $request['transaction_id'],
						'browser' 					       =>  $_SERVER['HTTP_USER_AGENT'],
						'ip_address'            	       => WC_Geolocation::get_ip_address(),
						'cybersource_response_info'        => $request
					);

					self::log( 'Existing Order Number: ' . print_r( $cybersource_order_info, true ) );

					$email 		= get_option('admin_email');
					$subject 	= "The customer is using an existing Order ID #".$cybersource_order_info['cybersource_transaction_order_id'];
					$heading 	= $subject; 
					$message 	= 'Response Logs: ' . print_r( $cybersource_order_info, true );

					$email_headers = array('Content-Type: text/html; charset=UTF-8');
					$mailer = WC()->mailer();
					$wrapped_message = $mailer->wrap_message($heading, $message);
					$wc_email = new WC_Email;
					$html_message = $wc_email->style_inline($wrapped_message);
					$mailer->send( $email, $subject, $html_message, $email_headers );

					wc_add_notice( __( sprintf( "Transaction Error: '%s'", "Sorry something went wrong on your order, Please contact the support!" ) , 'woocommerce'), "error" );
					wp_safe_redirect( add_query_arg( 'error', "declined", wc_get_checkout_url() ) );	
					exit;

				}

				//stored important keys for counter checking
				// update_post_meta( $order_id, '_cyber_transaction_id', $transaction_id );
				// update_post_meta( $order_id, '_cyber_decision_id', $decision );
				// update_post_meta( $order_id, '_' . $this->id . '_request_token', $request_token );

				$order->update_meta_data( '_cyber_transaction_id', $transaction_id );
				$order->update_meta_data( '_cyber_decision_id', $decision );
				$order->update_meta_data(  '_' . $this->id . '_request_token', $request_token );				
				$order->save();

				$api_integration = get_post_meta($order_id , '_cb_integration', true );

				//signed field names signature verification
				//$signed_field_names = explode( ",", $request['signed_field_names'] );

				switch ( $api_integration ) {
					case 'sawm': // Secure Acceptance Web/Mobile
					case 'subscriptions': // Subscription	
						$secret_key = $this->secret_key; 
						break;
						
					case 'sasop': //Secure Acceptance Silent Order POST
					case 'subscriptions_sop': // Subscription SOP	
						$secret_key = $this->secret_key_sop;
						break;
				
				}

				//unset($request['wc-api']);
				//if enable cybersource verification
				if( $this->enable_signature === true ){

					if (strcmp($request["signature"], $this->sign($request, $secret_key))==0) {
						// cybersource signature verified
					} else {
						$error_message = "Cybersource Signature Verification failed!";
						self::log( "Transaction Error Signature Verification: " . print_r( $request, true ) );
						wc_add_notice( __( sprintf( "Transaction Error: '%s'", $error_message ) , 'woocommerce'), "error" );
						$order->add_order_note( sprintf( "%s Payments Transaction was declined: '%s'", $this->method_title, $error_message) ); 
						$order->update_status( 'failed' );
						wp_safe_redirect( add_query_arg( 'error', "declined", wc_get_checkout_url() ) );
						exit;
					}

				}

				//Merchant Notification
				if( $mnp == true ){
					$this->merchant_notification( $request, $order );
					exit;
				}

					//Customer Response URL
					switch( $decision ){
						case 'ACCEPT':

							$order->payment_complete( $transaction_id );

							$order_status = $this->virtual_order_payment_complete_order_status( $order->get_id() );

							if( $this->default_status == 'default' ){
								//Virtual product
								if($order_status == 'completed' ){
									$order->update_status( $order_status );
								} else {
									$order->update_status( 'processing' );
								}
							} else {
								$order->update_status( $this->default_status );
							}
							
							$order->add_order_note(
								sprintf(
									"%s Payment Completed with Transaction Id of '%s'",
									$this->method_title,
									$transaction_id
								)
							);

							    //update_post_meta( $order->get_id() , '_' . $this->id . '_transaction_id', $transaction_id );
								$order->update_meta_data( '_' . $this->id . '_transaction_id', $transaction_id );
								$order->save();

								$save_card = get_post_meta( $order->get_id(), '_confirm_save_card', true );
								$cb_card_token = get_post_meta( $order->get_id(), '_cb_card_token', true );

								if( $save_card == 'on' || $cb_card_token == 'new' ){

									// WC Payment Token & Save Card Support
									$req_card_expiry_date = explode( "-", $req_card_expiry_date );
									$card_info = array( 'set_last4' 		=> substr( $req_card_number , -4 ),
														'set_expiry_month' 	=> $req_card_expiry_date[0],
														'set_expiry_year' 	=> $req_card_expiry_date[1],
														'card_type' 		=> $req_score_card_account_type,
														'token'             => $request_token,
														'user_id'	        => $customer_id,
													);

									self::log( 'Card Info: ' . print_r( $card_info, true ) );
									update_user_meta( get_current_user_id(), $this->id . '_customer_token', $request_token);
									// save payment token	
									$this->save_token($card_info);
									

								}	
								
								$woocommerce->cart->empty_cart();

								//WPML Integration

								if ( is_plugin_active( 'sitepress-multilingual-cms/sitepress.php' ) ) {
									$wpml_current_lang = get_post_meta( $order->get_id() , '_cybersource_wpml', true );
								} else {
									$wpml_current_lang = "";
								}
								
								
								if($this->custom_thankyou == '' ){

									if( !empty($wpml_current_lang)){
										
										$url 		= apply_filters( 'wpml_permalink', $order->get_checkout_order_received_url()  , $wpml_current_lang , true ); 
										$order_key 	= $order->get_order_key();
										$find 		= "?key=" . $order_key;
										$replace 	= "order-received/".$order->get_id()."/?key=" . $order_key;

										$return_url = str_replace($find, $replace, $url );

										wp_safe_redirect($return_url);

									} else {
										wp_safe_redirect(  $this->get_return_url( $order ) );
									}

								} else {

									if( !empty($wpml_current_lang)){
										$url_redirect = apply_filters( 'wpml_permalink', get_page_link($this->custom_thankyou) , $wpml_current_lang , true ); 
										wp_safe_redirect($url_redirect);
									} else {
										wp_safe_redirect( get_page_link($this->custom_thankyou) ); 
									}
									
								}
								
								exit;
											
							break;
						case 'DECLINE':

							$order->update_status( 'failed' );

							$rs = $this->reason_code($reason_code);

							$invalid_fields = !empty( $_REQUEST[ 'invalid_fields'] ) ? wc_clean($_REQUEST['invalid_fields']) : '';

							if( !empty($rs)){
								if(!empty($invalid_fields)){
									$error_msg = __( sprintf( "Transaction Error: %s [ %s ]", $rs, $invalid_fields  ) , 'woocommerce');
								} else {
									$error_msg = __( sprintf( "Transaction Error: %s ", $rs  ) , 'woocommerce');
								}
								
							} else {
								$error_msg = __( sprintf( "Transaction Error: '%s' with reason code '%s'", $message, $reason_code  ) , 'woocommerce');
							}
							
							$order->add_order_note( sprintf( "%s Payments Transaction was declined: '%s'", $this->method_title, $error_msg ) ); 
																				
							if($this->secured_message === true ){
								$error_msg = __( sprintf( "Transaction rejected, please contact your bank. Reference Number: %s", $transaction_id ) , 'woocommerce');
								wc_add_notice( $error_msg, "error" );	
								add_post_meta( $order->get_id(), '_cybersource_error_msg', $error_msg );
							} else {
								wc_add_notice( $error_msg, "error" );
								add_post_meta( $order->get_id(), '_cybersource_error_msg', $error_msg );
							}
							
							if($this->custom_decline == '' ){
								//wp_safe_redirect( add_query_arg( 'error', $order->get_order_key(), wc_get_checkout_url() ) );	
								wp_safe_redirect( add_query_arg( 'error', "declined", wc_get_checkout_url() ) );
								exit;
							} else {
								$url_redirect = add_query_arg( 'order_key', $order->get_order_key(), get_page_link($this->custom_decline) ); 
								wp_safe_redirect( $url_redirect );
							}
							exit;
																								
							break;
						case 'REVIEW': 
							$order->update_status( 'on-hold', __(  $message , 'woocommerce' ));
							$order->reduce_order_stock();
							$order->add_order_note(
								sprintf(
									"%s Payment on-hold with Transaction Id of '%s' with reason code '%s'",
									$this->method_title,
									$transaction_id,
									$reason_code
								)
							);
							
							$woocommerce->cart->empty_cart();
						
							if($this->custom_thankyou == '' ){
								wp_safe_redirect(  $this->get_return_url( $order ) );
							} else {
								wp_safe_redirect( get_page_link($this->custom_thankyou) ); 
							}
							
							exit;
									
							break;
						case 'ERROR':

							$order->update_status( 'failed' );

							$rs = $this->reason_code($reason_code);

							$invalid_fields = !empty( $_REQUEST[ 'invalid_fields'] ) ? wc_clean($_REQUEST['invalid_fields']) : '';

							if( !empty($rs)){
								if(!empty($invalid_fields)){
									$error_msg = __( sprintf( "Transaction Error: %s [ %s ]", $rs, $invalid_fields  ) , 'woocommerce');
								} else {
									$error_msg = __( sprintf( "Transaction Error: %s ", $rs  ) , 'woocommerce');
								}
								
							} else {
								$error_msg = __( sprintf( "Transaction Error: '%s' with reason code '%s'", $message, $reason_code  ) , 'woocommerce');
							}

							$order->add_order_note( sprintf( "%s Payments Failed: '%s' ", $this->method_title, $error_msg ) ); 

							if($this->secured_message === true){

								$error_msg =  __( sprintf( "Transaction failed, please contact your bank. Reference Number: %s", $transaction_id ) , 'woocommerce');
								add_post_meta( $order->get_id(), '_cybersource_error_msg', $error_msg );
								wc_add_notice( $error_msg, "error" );

							} else {
																
								add_post_meta( $order->get_id(), '_cybersource_error_msg', $error_msg );
								wc_add_notice( $error_msg, "error" );	
								
							}
														
							if($this->custom_error == '' ){							
								//wp_safe_redirect( add_query_arg( 'error', $order->get_order_key(), wc_get_checkout_url() ) );exit;						
								wp_safe_redirect( add_query_arg( 'error', "declined", wc_get_checkout_url() ) );
								exit;
							} else {
								$url_redirect = add_query_arg( 'order_key', $order->get_order_key(), get_page_link($this->custom_error) );
								wp_safe_redirect( $url_redirect ); exit;
							}
							
							

							break;		
						case 'CANCEL':

							$order->update_status( 'cancelled' );
							$order->add_order_note( sprintf( "%s Payments Failed: '%s' with reason code '%s'", $this->method_title, $message, $reason_code ) ); 
							wc_add_notice( __( "Cancelled: ". $message , 'woocommerce'), "error" );
							
							if($this->custom_cancel == '' ){
								wp_safe_redirect( add_query_arg( 'cancelled', 'true', wc_get_checkout_url() ) );exit;	
							} else {
								wp_safe_redirect( get_page_link($this->custom_cancel) ); exit;
							}
							
							break;			
					}

				
				
			}
			die();
		}

		//* Error message in the page checkout

		public function woocommerce_before_checkout_form(){


			if ( isset( $_REQUEST['cancelled'] ) ){
				wc_add_notice( __( 'Transaction cancelled. Please try again.', 'woocommerce' ), 'error' );
			}			

			
			if ( isset( $_REQUEST['error'] ) ){

				$order_key = wc_clean($_REQUEST['error']);
				$order_id 	= wc_get_order_id_by_order_key($order_key);
			
				$message 	= get_post_meta( $order_id, '_cybersource_error_msg' );
			
			
				if( !empty($message) ){
					$result =  __( end($message), 'woocommerce' );
					wc_add_notice( __($result, 'woocommerce' ), 'error' );	
				}	 
				
			}


		}

		public function merchant_notification( $request, $order ){

			$order_data 	= $order->get_data();
			$reason_code 	= wc_clean ( $request[ 'reason_code' ] );
			$req_card_type 	= wc_clean ( $request[ 'req_card_type' ] );
			$req_currency 	= wc_clean ( $request[ 'req_currency' ] );
			$req_reference_number 	= wc_clean ( $request[ 'req_reference_number' ] );
			$decision 			= wc_clean ( $request[ 'decision' ] );
			$message 			= wc_clean ( __( $request[ 'message' ] , 'woocommerce' ) );
			$req_amount 		= wc_clean ( $request[ 'req_amount' ] );
			$req_payment_method = wc_clean ( $request[ 'req_payment_method' ] );
			$transaction_id 	= wc_clean ( $request[ 'transaction_id' ] );
			$transaction_uuid   = wc_clean ( $request[ 'req_transaction_uuid' ] );
			$customer_id 		= $order->get_user_id();

			if( ! empty($request[ 'req_card_number' ])){
					$req_card_number = wc_clean ( $request[ 'req_card_number' ]);	
			} else {
				$req_card_number = wc_clean ( $request[ 'req_echeck_account_number' ]);	
			}

			if( ! empty( $request[ 'payment_token' ] )){
				$request_token   = wc_clean ( $request[ 'payment_token' ]);
			}

			if( ! empty($request[ 'req_card_type' ])){
				$req_card_type   = wc_clean ( $request[ 'req_card_type' ]);
			} else {
				$req_card_type   = wc_clean ( $request[ 'req_payment_method' ]);
			}

			if( ! empty($request[ 'req_card_expiry_date' ])){
				$req_card_expiry_date   = wc_clean ( $request[ 'req_card_expiry_date' ]);
			} else{
				$req_card_expiry_date   = 'NA';
			}

			if( ! empty($request[ 'score_card_account_type' ])){
				$req_score_card_account_type   = wc_clean ( $request[ 'score_card_account_type' ]);
			} else{
				$req_score_card_account_type   = $this->get_card_types(wc_clean ( $request[ 'req_card_type' ]));
			}

				switch( $decision ){
					case 'ACCEPT':

						$order->payment_complete( $transaction_id );

						//update_post_meta( $order->get_id() , '_' . $this->id . '_transaction_id', $transaction_id );

						$order->update_meta_data(  '_' . $this->id . '_transaction_id', $transaction_id );
						$order->save();

						$order_status = $this->virtual_order_payment_complete_order_status( $order->get_id() );

						if( $this->default_status == 'default' ){
							$order->update_status( $order_status );
						} else {
							$order->update_status( $this->default_status );
						}	
						
            			
						$order->add_order_note(
							sprintf(
								"%s Payment Completed with Transaction Id of '%s'",
								$this->method_title,
								$transaction_id
							)
						);

						$save_card = get_post_meta( $order->get_id(), '_confirm_save_card', true );

						if( $save_card == 'on' ){
							
							// WC Payment Token & Save Card Support
							$req_card_expiry_date = explode( "-", $req_card_expiry_date );
							$card_info = array( 'set_last4' 		=> substr( $req_card_number , -4 ),
												'set_expiry_month' 	=> $req_card_expiry_date[0],
												'set_expiry_year' 	=> $req_card_expiry_date[1],
												'card_type' 		=> $req_score_card_account_type,
												'token'             => $request_token	
											);

							self::log( 'Card Info: ' . print_r( $card_info, true ) );
							update_user_meta( get_current_user_id(), $this->id . '_customer_token', $request_token);
							// save payment token	
							$this->save_token($card_info);

						}	

					break;

					case 'DECLINE':
						$order->update_status( 'failed' );
						$order->add_order_note( sprintf( "%s Payments Transaction was declined: '%s' with reason code '%s'", $this->method_title, $message , $reason_code) ); 
					break;

					case 'REVIEW':

						$order->update_status( 'on-hold', __(  $message , 'woocommerce' ));
						//$order->reduce_order_stock();
						$order->add_order_note(
							sprintf(
								"%s Payment on-hold with Transaction Id of '%s' with reason code '%s'",
								$this->method_title,
								$transaction_id,
								$reason_code
							)
						);
						
					break;

					case 'ERROR':
						$order->update_status( 'failed' );
						$order->add_order_note( sprintf( "%s Payments Failed: '%s' with reason code '%s'", $this->method_title, $message, $reason_code ) ); 
					break;

					case 'CANCEL':
						$order->update_status( 'cancelled' );
						$order->add_order_note( sprintf( "%s Payments Failed: '%s' with reason code '%s'", $this->method_title, $message, $reason_code ) ); 

					break;
				}

			

		}
		
		public static function log( $message ) {
			if ( self::$log_enabled == 'yes' ) {
				if ( empty( self::$log ) ) {
					self::$log = new WC_Logger();
				}
				self::$log->add( 'Cybersource' , $message );
			}
		}

		public function virtual_order_payment_complete_order_status( $order_id ){
        
		    //$order = new WC_Order( $order_id );
		    $order = wc_get_order( $order_id );
		    $order_data = $order->get_data(); 

		    $virtual_order = null;

		    if ( count( $order->get_items() ) > 0 ) {

		        foreach( $order->get_items() as $item ) {

		          if ( 'line_item' == $item['type'] ) {
						
						$_product = wc_get_product( $item['product_id'] );
					
		                if ( ! $_product->is_virtual() ) {
		                  $virtual_order = false;
		                  break;
		                } else {
		                  $virtual_order = true;
		                }
		          }
		        }
		    }

		    // virtual order, mark as completed
		    if ( $virtual_order ) {
		      return 'completed';
		    }


		    // non-virtual order, return original status
		    return $order_data['status'];
  		}

  		public function generate_header_html( $key, $data ) {
			$field_key = $this->get_field_key( $key );
			$defaults  = array(
				'title'             => '',
				'label'             => '',
				'type'              => 'text',
				'description'       => ''
			);

			$data = wp_parse_args( $data, $defaults );

			if ( ! $data['label'] ) {
				$data['label'] = $data['title'];
			}

			ob_start();
			?>
			<tr valign="top">
				<th scope="row" class="titledesc" colspan="2">
					<h2 for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></h2>
					<?php echo $this->get_description_html( $data ); ?>
				</th>
			</tr>
			<?php

			return ob_get_clean();
		}

		public function generate_hr_html( $key, $data ) {
			$field_key = $this->get_field_key( $key );
			$defaults  = array(
				'title'             => '',
				'label'             => '',
				'type'              => 'hr',
				'description'       => ''
			);

			$data = wp_parse_args( $data, $defaults );

			if ( ! $data['label'] ) {
				$data['label'] = $data['title'];
			}

			ob_start();
			?>
			<tr valign="top">
				<th scope="row" class="titledesc" colspan="2">
					<hr>
				</th>
			</tr>
			<?php

			return ob_get_clean();
		}

		public function add_http_header_cb($headers) {

		    if ( empty( $headers['Referer']) ) {
		        $headers['Referer'] = wp_get_referer();    
		    }


		    return $headers;     
		}



		public  function get_cc_type( $cardnum ) { 
	  		
	  		/* Visa */
	  		
		    if ( preg_match( "/^4(\d{12}|\d{15})$/", $cardnum ) ) { 
		    	$type = '001'; 
		    		
		    /* MasterCard */	
		    		
		    } else if( preg_match( "/^5[1-5]\d{14}$/", $cardnum ) ) { 
		    	$type = '002'; 
		    	
		    /* American Express */	
		    	
	  		} else if( preg_match( "/^3[47]\d{13}$/", $cardnum ) ) { 
	  			$type = '003';
	  			
	  		/* Discover */
	  				
	  		} else if( preg_match( "/^6011\d{12}$/", $cardnum ) ){ 
	  			$type = '004'; // Discover
	  			
	  		/* Diners Club */
	  					
			} else if( preg_match( "/^[300-305]\d{11}$/", $cardnum ) || 
		      preg_match( "/^3[68]\d{12}$/", $cardnum ) ){ 
		      	$type = '005'; 
		      	
		    /* EnRoute */
		      	  	
		    } else if ( preg_match( "/^2(014|149)\d{11}$/", $cardnum) ) {
		      $type = '014'; 
		
		     /* JCB */
		       
		    } else if ( preg_match( "/^3\d{15}$/", $cardnum ) || 
		      preg_match("/^(2131|1800)\d{11}$/", $cardnum)) {
		      $type = '007'; 
		      
		      /* Maestro */
		    } else if ( preg_match( "/^(?:5020|6\\d{3})\\d{12}$/", $cardnum ) ) {
		      $type = '024';     
		    
		     /* Visa Electron */
		    
		    } else if ( preg_match( "/^4(17500|917[0-9][0-9]|913[0-9][0-9]|508[0-9][0-9]|844[0-9][0-9])\d{10}$/", $cardnum ) ) {
		     $type = '033';
		     
		     /*Laser*/
		    
		    } else if ( preg_match( "/^(6304|670[69]|6771)[0-9]{12,15}$/", $cardnum ) ) {
		     $type = '035';
		     
		     /* Carte Blanche */
		     
		   }else if(preg_match("/^389[0-9]{11}$/", $cardnum)){
		     $type = '006';
		
		     /* Dankort */
		     
		   }else if(preg_match("/^5019\d{12}$/", $cardnum)){
		     $type = '034';
		   
		  }else{
		      	$type = '';
		  } 
		     
	       
	    return $type; 
		} 

		/**
		 * Get gateway icon.
		 *
		 * @access public
		 * @return string
		 */
		public function get_icon() {

			if( ! empty( $this->cards ) && is_array($this->cards )){
				$icon = '';
				foreach ( $this->cards as $key => $value) {
					$icon  .= '<img src="' . esc_url(WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/'.$value.'.svg' )) . '" alt="'.ucwords($value).'" width="32" />';
				}

			} else {
				$icon = '';
			}
			

			return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
		}


		public function save_token( $params ){
			
			$customer_token = get_user_meta( get_current_user_id(), $this->id . '_customer_token', true );
			$customer_token_id = null;
			
			// Add New Customer Card Token
			$customer_tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), $this->id );

			if( ! empty($customer_tokens)){
				foreach ( $customer_tokens as $c_token ) {
					if ( $c_token->get_token() == $customer_token ) {
						$customer_token_id = $c_token->get_id();
						break;
					}
				}
			}

			if( $customer_token_id  == null ){
				$token = new WC_Payment_Token_CC();
			} else {
				$token = WC_Payment_Tokens::get( $customer_token_id );
			}

			$token->set_token(  $params[ 'token' ] );
			$token->set_gateway_id( $this->id );
			$token->set_card_type( $params[ 'card_type' ] );
			$token->set_last4( $params[ 'set_last4' ] );
			$token->set_expiry_month(  $params['set_expiry_month'] );
			$token->set_expiry_year(  $params['set_expiry_year'] );

			if ( is_user_logged_in() ) {
				$token->set_user_id( get_current_user_id() );			
			} else {
				$token->set_user_id( $params['user_id'] );
			}

			//var_dump( $token->validate() ); // bool(true)
			$result = $token->save();

			if( $result == true ){
			return $token;
			} else {
			return null;
			}


		}

		public function get_card_types( $code ){

			if( empty($code)) return;

			$card_types['001'] = __( 'Visa' , 'woocommerce' );
			$card_types['002'] = __( 'MasterCard' , 'woocommerce' );
			$card_types['003'] = __( 'American Express' , 'woocommerce' );
			$card_types['004'] = __( 'Discover' , 'woocommerce' );
			$card_types['005'] = __( 'Diners Club' , 'woocommerce' );
			$card_types['006'] = __( 'Carte Blanche' , 'woocommerce' );
			$card_types['007'] = __( 'JCB' , 'woocommerce' );
			$card_types['014'] = __( 'EnRoute' , 'woocommerce' );
			$card_types['021'] = __( 'JAL' , 'woocommerce' );
			$card_types['024'] = __( 'Maestro UK Domestic' , 'woocommerce' );
			$card_types['031'] = __( 'Delta' , 'woocommerce' );
			$card_types['033'] = __( 'Visa Electron' , 'woocommerce' );
			$card_types['034'] = __( 'Dankort' , 'woocommerce' );
			$card_types['036'] = __( 'Carte Bleue' , 'woocommerce' );
			$card_types['037'] = __( 'Carta Si' , 'woocommerce' );
			$card_types['042'] = __( 'Maestro International' , 'woocommerce' );
			$card_types['043'] = __( 'GE Money UK card' , 'woocommerce' );
			$card_types['050'] = __( 'Hipercard' , 'woocommerce' );
			$card_types['054'] = __( 'Elo' , 'woocommerce' );

			if (array_key_exists($code, $card_types)) {
				return $card_types[$code];
			} else{
				return 'Card';
			}

			
		}

		public function reason_code( $code = '' ){

			$reason_code = array(
				'100' => __( 'Successful transaction.', 'woocommerce' ),
				'101' => __( 'The request is missing one or more required fields.', 'woocommerce' ),
				'102' => __( 'One or more fields in the request contains invalid data.', 'woocommerce' ),
				'110' => __( 'Only a partial amount was approved.', 'woocommerce' ),
				'150' => __( 'Error: General system failure.', 'woocommerce' ),
				'151' => __( 'Error: The request was received but there was a server timeout.', 'woocommerce' ),
				'152' => __( 'Error: The request was received, but a service did not finish running in time.', 'woocommerce' ),
				'200' => __( 'The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the Address Verification Service (AVS) check.', 'woocommerce' ),
				'201' => __('The issuing bank has questions about the request.', 'woocommerce' ),
				'202' => __( 'Expired card.', 'woocommerce' ),
				'203' => __( 'General decline of the card.', 'woocommerce' ),
				'204' => __( 'Insufficient funds in the account.', 'woocommerce' ),
				'205' => __( 'Stolen or lost card.', 'woocommerce' ),
				'207' => __( 'Issuing bank unavailable.', 'woocommerce' ),
				'208' => __( 'Inactive card or card not authorized for card-not-present transactions.', 'woocommerce' ),
				'209' => __( 'American Express Card Identification Digits (CID) did not match.', 'woocommerce' ),
				'210' => __( 'The card has reached the credit limit.', 'woocommerce' ),
				'211' => __( 'Invalid CVN.', 'woocommerce' ),
				'221' => __( 'The customer matched an entry on the processor\'s negative file.', 'woocommerce' ),
				'230' => __( 'The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the CVN check.', 'woocommerce' ),
				'231' => __( 'Invalid credit card number.', 'woocommerce' ),
				'232' => __( 'The card type is not accepted by the payment processor.', 'woocommerce' ),
				'233' => __( 'General decline by the processor.', 'woocommerce' ),
				'234' => __( 'There is a problem with your CyberSource merchant configuration.', 'woocommerce' ),
				'235' => __( 'The requested amount exceeds the originally authorized amount.', 'woocommerce' ),
				'236' => __( 'Processor failure.', 'woocommerce' ),
				'237' => __( 'The authorization has already been reversed.', 'woocommerce' ),
				'238' => __( 'The authorization has already been captured.', 'woocommerce' ),
				'239' => __( 'The requested transaction amount must match the previous transaction amount.', 'woocommerce' ),
				'240' => __( 'The card type sent is invalid or does not correlate with the credit card number.', 'woocommerce' ),
				'241' => __( 'The request ID is invalid.', 'woocommerce' ),
				'242' => __( 'You requested a capture, but there is no corresponding, unused authorization record.', 'woocommerce' ),
				'243' => __( 'The transaction has already been settled or reversed.', 'woocommerce' ),
				'246' => __( 'The capture or credit is not voidable because the capture or credit information has already been submitted to your processor. Or, you requested a void for a type of transaction that cannot be voided.', 'woocommerce' ),
				'247' => __( 'You requested a credit for a capture that was previously voided.', 'woocommerce' ),
				'250' => __( 'Error: The request was received, but there was a timeout at the payment processor.', 'woocommerce' ),
				'520' => __( 'The authorization request was approved by the issuing bank but declined by CyberSource based on your Smart Authorization settings.', 'woocommerce' ),
			);

			return $reason_code[$code];

		}

		public function strip_extra_char($text){
			return str_replace(['"',"'"], "", $text);
		}

		public function soaptoolkit_request(){

			// Cybersource WSDL Endpoint URL 
			if( $this->mode  == 'p' ){
				$wsdl_uri = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.26.wsdl';
			}

			else{
				$wsdl_uri = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.26.wsdl';
			}

			//echo $wsdl_uri;

				// Cybersource Soap Client Request
				return new CybsSoapClient(
						array(
								'merchant_id' 		=> $this->merchant_id ,
								'transaction_key' 	=> $this->transaction_key,
								'wsdl'				=> $wsdl_uri
							)
					);
	
		}
		
		public function reversal_payment ( $order_id, $amount = null, $reason = '' ) {

			$order = wc_get_order( $order_id );
			$currency = $order->get_currency();

			$transaction_id = get_post_meta( $order_id, '_'. $this->id .'_transaction_id' , true );
			$request_token = get_post_meta( $order_id, '_'. $this->id .'_request_token' , true );
			$capture_request_id = get_post_meta( $order_id, '_'. $this->id .'_capture_request_id' , true );

			if ( ! $transaction_id ) {
				return new WP_Error( $this->id . '_refund_error',
					 esc_html__( sprintf(
						'%s Credit Card Reversal failed because the Transaction ID is missing.',
						ucwords($this->id)
					), 'woocommerce' )
				);
			}
			
			$soap = $this->soaptoolkit_request(); 
			$request = $soap->createRequest( $currency);
			
			$request->clientLibrary 		= "WooCommerce PHP Client";
			$request->clientLibraryVersion 	= phpversion();
			$request->clientEnvironment 	= php_uname();
			$request->merchantID 			= $this->merchant_id;			
			$request->merchantReferenceCode = $order_id;
			
			$cc_auth_reversal_service = new \stdClass();
			$cc_auth_reversal_service->run = 'true';
			$cc_auth_reversal_service->authRequestID = $transaction_id;
			$request->ccAuthReversalService = $cc_auth_reversal_service;
			
			// if there was an amount specified, just use it - otherwise add the individual items
			//$request->purchaseTotals->currency =  $currency;
			$request->purchaseTotals = (object) array( 'currency' => $currency );

			if ( $amount !== null ) {
				//$request->purchaseTotals->grandTotalAmount = $amount;
				$request->purchaseTotals = (object) array( 'grandTotalAmount' => (double) number_format( $amount, 2, ".", "") );
			} else {
				//$request->purchaseTotals->grandTotalAmount =  $order->get_total();
				$request->purchaseTotals = (object) array( 'grandTotalAmount' => (double) number_format( $order->get_total(), 2, ".", "") );

			}

			$this->log( 'Cybersource Request - SOP: ' . print_r( $request, true ) );

			$response = $soap->runTransaction( $request );

			$this->log( 'Cybersource Response - SOP: ' . print_r( $response, true ) );
			
			if( $response->decision == 'ACCEPT' ){

				$order->add_order_note(
					esc_html__( sprintf(
						'%1$s Reversal %2$s with amount of %3$s',
						$this->method_title,
						sanitize_text_field($response->decision),
						sanitize_text_field($response->ccAuthReversalReply->amount .' '. $response->purchaseTotals->currency)
					), 'woocommerce' )
				);

				return true;
 
			} else {

				$err_msg = esc_html__($this->reason_code($response->ccAuthReversalReply->reasonCode));

				$order->add_order_note(
					esc_html__( sprintf(
						'%1$s Reversal %2$s, %3$s',
						$this->method_title,
						sanitize_text_field($response->decision),
						sanitize_text_field($err_msg)
					), 'woocommerce' )
				);
				
				return new WP_Error( $this->id . '_refund_error', 
					esc_html__( ucwords($this->method_title). ' ' . 'Reversal Payment Failed, ' . sanitize_text_field($err_msg) , '','woocommerce' ) );

			}
			
		}

		public function void_payment ( $order_id, $amount = null, $reason = '' ) {

			$order = wc_get_order( $order_id );

			$transaction_id = get_post_meta( $order_id, '_'. $this->id .'_transaction_id' , true );
			$request_token = get_post_meta( $order_id, '_'. $this->id .'_request_token' , true );

			if ( ! $transaction_id ) {
				return new WP_Error( $this->id . '_refund_error',
					 esc_html__( sprintf(
						'%s Credit Card Void failed because the Transaction ID is missing.',
						ucwords($this->id)
					), 'woocommerce' )
				);
			}
			
			$soap = $this->soaptoolkit_request(); 
			$request = $soap->createRequest( $currency);
			
			$request->clientLibrary 		= "WooCommerce PHP Client";
			$request->clientLibraryVersion 	= phpversion();
			$request->clientEnvironment 	= php_uname();
			$request->merchantID 			= $this->merchant_id;			
			$request->merchantReferenceCode = $order_id;
			
			$void_service = new \stdClass();
			$void_service->run = 'true';
			$void_service->voidRequestID = $transaction_id;
			$request->voidService = $void_service;

			$this->log( 'Cybersource Request - SOP: ' . print_r( $request, true ) );

			$response = $soap->runTransaction( $request );

			$this->log( 'Cybersource Response - SOP: ' . print_r( $response, true ) );
			
			if( $response->decision == 'ACCEPT' ){

				$order->add_order_note(
					esc_html__( sprintf(
						'%1$s Void %2$s with Amount of %3$s',
						$this->method_title,
						sanitize_text_field($response->decision),
						sanitize_text_field($response->voidReply->amount. ' ' . strtoupper($response->voidReply->currency))
					), 'woocommerce' )
				);

				return true;
 
			} else {

				$err_msg = esc_html__($this->reason_code($response->voidReply->reasonCode));

				$order->add_order_note(
					esc_html__( sprintf(
						'%1$s Void %2$s, %3$s',
						$this->method_title,
						sanitize_text_field($response->decision),
						sanitize_text_field($err_msg)
					), 'woocommerce' )
				);
				
				return new WP_Error( $this->id . '_refund_error', esc_html__( ucwords($this->method_title). ' ' . 'Void Payment Failed,' . sanitize_text_field($err_msg)  , '','woocommerce' ) );

			}
			
		}

		public function cybersource_custom_validate_address_fields() {
		
				if(!empty($this->address_input_size)){
					$min_length = $this->address_input_size; // All other processors 
				} else {
			
					// Define the minimum length for the address fields
					$min_length = 60; // All other processors 
			
				}
				
				// Get the billing and shipping address fields
				$billing_address_1 = isset( $_POST['billing_address_1'] ) ? sanitize_text_field( $_POST['billing_address_1'] ) : '';
				$billing_address_2 = isset( $_POST['billing_address_2'] ) ? sanitize_text_field( $_POST['billing_address_2'] ) : '';
				$shipping_address_1 = isset( $_POST['shipping_address_1'] ) ? sanitize_text_field( $_POST['shipping_address_1'] ) : '';
				$shipping_address_2 = isset( $_POST['shipping_address_2'] ) ? sanitize_text_field( $_POST['shipping_address_2'] ) : '';
				
				// Check if the address fields meet the minimum length requirement
				if ( strlen( $billing_address_1 ) > $min_length || strlen( $billing_address_2 ) > $min_length || strlen( $shipping_address_1 ) > $min_length || strlen( $shipping_address_2 ) > $min_length ) {
					// Display an error message
					wc_add_notice( __( 'Please enter a valid address not more than '.$min_length.' characters.', 'woocommerce' ), 'error' );
					return false;
				}
			
		}

    }

	// MDD settings
	include plugin_dir_path( __FILE__ ).'wc-cybersource-mdd.php';
	include plugin_dir_path( __FILE__ ).'wc-cybersource-mdd-override.php';

	// Addons Cybersource API Integration
    include plugin_dir_path( __FILE__ ).'wc-cybersource-wm.php';
    include plugin_dir_path( __FILE__ ).'wc-cybersource-sop.php';

    // Cybersource Library
	if( class_exists( 'SoapClient' ) ){
		include plugin_dir_path( __FILE__ ).'lib/CybsClient.php';    
		include plugin_dir_path( __FILE__ ).'lib/CybsSoapClient.php';    	
		include plugin_dir_path( __FILE__ ).'wc-cybersource-so.php';
	}

	// Device Fingerprint ID Profiler

	include plugin_dir_path( __FILE__ ).'wc-device-fingerprint-id.php';
	
    function woocommerce_add_cybersource_sawm( $methods ) {

    		$cb_api = get_option( 'woocommerce_cybsawm_settings' );

    		if( ! empty( $cb_api )){
    			$integration = $cb_api[ 'cb_api' ];
    		} else {
    			$integration = 'sawmsop';
    		}

    		switch ( $integration ) {
    			case 'sawmsop': // Secure Acceptance Web/Mobile & Silent Order POST
    				$methods[] = 'WC_API_Cybersource_SAWM';
    				break;

    			case 'sawm': // Secure Acceptance Web/Mobile
    				$methods[] = 'WC_API_Cybersource_WM';
    				break;
    				
    			case 'sasop': //Secure Acceptance Silent Order POST
    				$methods[] = 'WC_API_Cybersource_SOP';
    				break;
    				
    			case 'so': //Simple Order API (SOAP)
					if( class_exists( 'SoapClient' ) ){
						$methods[] = 'WC_API_Cybersource_SO';
					} else {
						$methods[] = 'WC_API_Cybersource_SAWM';
					}
    				
    				break;

    			case 'subscriptions': // Subscription

    				if( class_exists( 'WC_API_Cybersource_Subscriptions_Addon' )) {
    					$methods[] = 'WC_API_Cybersource_Subscriptions_Addon';	
    				} else {
    					// Admin Notice
    					// default Web/Mobile
    					$methods[] = 'WC_API_Cybersource_WM';
    				}

    				break;

    			case 'subscriptions_sop': // Subscription SOP

    				if( class_exists( 'WC_API_Cybersource_Subscriptions_SOP' )) {
    					$methods[] = 'WC_API_Cybersource_Subscriptions_SOP';	
    				} else {
    					// Admin Notice
    					// default Web/Mobile
    					$methods[] = 'WC_API_Cybersource_WM';
    				}

    				break;					
    			
    			default:
    				$methods[] = 'WC_API_Cybersource_SAWM';
    				break;
    		}
    		
            return $methods;
    }
    
    add_filter( 'woocommerce_payment_gateways', 'woocommerce_add_cybersource_sawm' );

	/* Ajax Service */
	include plugin_dir_path(__FILE__).'wc-cybersource-ajax.php';
	include plugin_dir_path(__FILE__).'wc-cybersource-ajax-call.php';
	

	add_action( 'wp_enqueue_scripts', array( 'WCCB_Ajax_Server' , 'ajax_local' ) );
	
    add_action( 'wp_ajax_nopriv_wccb-ajax-request', array( 'WCCB_Ajax_Server' , 'ajax_call' ) );
    add_action( 'wp_ajax_wccb-ajax-request', array( 'WCCB_Ajax_Server' , 'ajax_call' ) );

	
	
}

add_action('plugins_loaded', 'woocommerce_api_cybersource_sawm_init', 0);

// Add custom action links
//add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'cb_settings_action_links' );
function cb_settings_action_links( $links ) {
	
	$woo_version 	= version_compare( WC()->version, '2.6', '>=' );
	$section_slug   = $woo_version ? 'cybsawm' : strtolower( 'WC_API_Cybersource_SAWM' );
		
	$plugin_links = array(
		'<a href="' . esc_url(admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $section_slug )) . '">' . __( 'Settings', 'woocommerce' ) . '</a>',
	);
	return array_merge( $plugin_links, $links );	
}


add_action( 'admin_notices', 'cybersource_verify_soapclient_installed' );

function cybersource_verify_soapclient_installed(){

	$cb_api 		= get_option( 'woocommerce_cybsawm_settings' );

	if( empty($cb_api) ) return;

	$integration 	= $cb_api[ 'cb_api' ];

	if( ! empty( $cb_api ) && $integration == 'so' ){
		if( ! class_exists( 'SoapClient' ) ){
			?>
		<div class="notice notice-error is-dismissible">
			<p><?php echo __( 'WooCommerce CyberSource Payment Gateway Required <strong>PHP SOAP Client</strong> should be installed/enabled in your web server', 'woocommerce' )?></p>
		</div>
		<?php	
		}
	} 

}

add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'cybersource_docs_action_links' );

function cybersource_docs_action_links( $links ) {
  $plugin_links = array(
		'<a href="'. esc_url('https://ryanplugins.wordpress.com/2023/10/16/how-to-install-cybersource-payment-gateway-plugin/').'" target="_blank">' . __( 'Docs', 'woocommerce' ) . '</a>',
		'<a href="'.esc_url('https://codecanyon.net/item/woocommerce-cybersource-payment-gateway/12199526/support').'" target="_blank">' . __( 'Support', 'woocommerce' ) . '</a>',
	);
	return array_merge( $plugin_links, $links );
}

function cybersource_error_page_message( $atts ){

	 $order_key = wc_clean($_REQUEST['order_key']);
	 $order_id 	= wc_get_order_id_by_order_key($order_key);

	 $message 	= get_post_meta( $order_id, '_cybersource_error_msg' );
	 $result 	= '';

	 if( !empty($message) ){
		$result =  __( end($message), 'woocommerce' );
	 }	 

	return $result;
}

add_shortcode( 'cybersource_error_page_message', 'cybersource_error_page_message' );

// Check the billing address string length


/**
 * Custom function to declare compatibility with cart_checkout_blocks feature 
*/
function cybersource_declare_cart_checkout_blocks_compatibility() {
    // Check if the required class exists
    if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) {
        // Declare compatibility for 'cart_checkout_blocks'
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('cart_checkout_blocks', __FILE__, true);
    }
}
// Hook the custom function to the 'before_woocommerce_init' action
add_action('before_woocommerce_init', 'cybersource_declare_cart_checkout_blocks_compatibility');

// Hook the custom function to the 'woocommerce_blocks_loaded' action
add_action( 'woocommerce_blocks_loaded', 'cybersource_register_order_approval_payment_method_type' );

/**
 * Custom function to register a payment method type

 */
function cybersource_register_order_approval_payment_method_type() {
    // Check if the required class exists
    if ( ! class_exists( 'Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType' ) ) {
        return;
    }

    // Include the custom Blocks Checkout class
    require_once plugin_dir_path(__FILE__) . 'includes/class-cybersource-hosted-block-checkout.php';

    // Hook the registration function to the 'woocommerce_blocks_payment_method_type_registration' action
    add_action(
        'woocommerce_blocks_payment_method_type_registration',
        function( Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry $payment_method_registry ) {
            // Register an instance of WC_Cybersource_Hosted_Blocks
            $payment_method_registry->register( new WC_Cybersource_Hosted_Blocks );
        }
    );
}


//* Callback WooCommerce Error Classic Checkout only 
add_action( 'wp_footer', 'cybersource_action_woocommerce_error_callback', 10, 1 ); 

function cybersource_action_woocommerce_error_callback(){

	if(is_checkout() === true ){

		$payment_methods = (array) array_keys(WC()->payment_gateways()->get_available_payment_gateways());
		
		if(in_array( 'cybsawm', $payment_methods)){

			if( !empty($_REQUEST['error']) && $_REQUEST['error'] == "declined" ){
				wc_add_notice( __( 'Transaction Error: Payment Declined', 'woocommerce' ), 'error' );
				return false;
			}
			
		}

	}

}








