<?php
if ( ! defined( 'ABSPATH' ) ) exit;

class WC_API_Cybersource_SOP extends WC_API_Cybersource_SAWM 
{
	private $transaction_type;

	function __construct(){
		parent::__construct();

		$this->supports = array(
								 'products',
								 'default_credit_card_form',
								 'tokenization',
								 'refunds'
							  );


		$this->transaction_type = $this->settings[ 'transaction_type' ];		

		add_action( 'woocommerce_receipt_' .  $this->id , array( $this, 'receipt_page' ), 10, 1 );
		add_action( 'wp_enqueue_scripts', array( $this, 'script' ) );
		add_action( 'woocommerce_thankyou', array( $this , 'cybersource_thankyou_processing_order_status' ), 10 ,1);

		add_action('woocommerce_order_status_completed', array( $this, 'capture_order_status_completed' ), 10, 2 );
	}

	public function script(){

		if(is_checkout() === true && empty($_GET['order-pay'])){
			wp_enqueue_script( 'cybsawm-gateway-sop', plugins_url( 'assets/js/wc-cybersource-payment-sop.min.js', __FILE__ ), array( 'jquery', 'wc-credit-card-form' ), WC_VERSION, true );
		}
			
			
	}

	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 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 '<p>';
			}

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

		 //$this->credit_card_form();
		//WC_Payment_Gateway_CC::form();
		WC_Payment_Gateway_CC::payment_fields();
	}

	public function process_payment( $order_id ){
		
		global $woocommerce;

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

    	// Clean Session CC Data
    	$this->clean_cards_data( $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 SOP 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;

		}

    	// Get CC POST Data

		if( ! empty($_REQUEST['wc-cybsawm-payment-token']) && $_REQUEST['wc-cybsawm-payment-token'] != 'new' ){

			$token_id = !empty($_REQUEST['wc-cybsawm-payment-token']) ? $_REQUEST['wc-cybsawm-payment-token'] : '';

			if( empty($token_id)){
				wc_add_notice( __( 'Payment error: Card token is invalid', 'woocommerce'), "error" );
				return false;

			}

			$customer_token = WC_Payment_Tokens::get( $token_id );
			if(!empty($customer_token)){

				$card_token = $customer_token->get_token();
				$payment_token 		= wc_clean( $card_token );
				WC()->session->set( $this->id . '_' .$order_id. '_payment_token' , $payment_token );
 
			} else {
				wc_add_notice( __( 'Payment error: Customer Card token is invalid', 'woocommerce'), "error" );
				return false;
			}
			
			

		} else {

			if(!is_numeric($_REQUEST['cybsawm-cardnumber'])){

				wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Cardnumber!" ) , 'woocommerce'), "error" );
				return false;
	
			}
	
			if(!is_numeric($_REQUEST['cybsawm-card_cvc'])){
	
				wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Card code!" ) , 'woocommerce'), "error" );
				return false;
	
			}
	
			if(!is_numeric($_REQUEST['cybsawm-expiry_m'])){
	
				wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Expiry Month!" ) , 'woocommerce'), "error" );
				return false;
	
			}
	
			if(!is_numeric($_REQUEST['cybsawm-expiry_y'])){
	
				wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Expiry Year!" ) , 'woocommerce'), "error" );
				return false;
	
			}

			$card_number 		 = wc_clean( $_POST[ $this->id.'-cardnumber'] );
			$card_number 		 = str_replace( ' ', '', $card_number);
			$card_cvc    		 = wc_clean( $_POST[ $this->id.'-card_cvc'] );
			$card_exp_month 	 =  wc_clean( $_POST[ $this->id.'-expiry_m'] );
			$card_exp_year  	 =  wc_clean( $_POST[ $this->id.'-expiry_y'] );

			

			if( !empty($_REQUEST['wc-cybsawm-new-payment-method']) && $_REQUEST['wc-cybsawm-new-payment-method'] == "true"){
				WC()->session->set( $this->id . '_' .$order_id. '_save_token' , 1 );
			}

			WC()->session->set( $this->id . '_' .$order_id. '_card_number' , $card_number );
			WC()->session->set( $this->id . '_' .$order_id. '_card_cvc' , $card_cvc );

			$card_exp_month_count = strlen($card_exp_month);

			if($card_exp_month_count <= 1 ){
				$card_exp_month = "0".$card_exp_month;
			}

			$card_exp_year_count = strlen($card_exp_year);

			if( $card_exp_year_count == 4){
				$c_expiry_year = '-'.$card_exp_year;
			} elseif( $card_exp_year_count == 2){
				$c_expiry_year = '-20'.$card_exp_year;
			} else {
				wc_add_notice( __( 'Payment error: Card expiration date is invalid', 'woocommerce'), "error" );
				return false;
			}

			WC()->session->set( $this->id . '_' .$order_id. '_card_exp_year' , $card_exp_month.$c_expiry_year );

		}

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

		// Get mobile number for payer_authentication
		$billing_mobile_phone = !empty($_POST['billing_mobile_phone']) ? $_POST['billing_mobile_phone'] : ''; 
		$customer_browser_screen_height = !empty($_POST['customer_browser_screen_height']) ? $_POST['customer_browser_screen_height'] : '';
		$customer_browser_screen_width = !empty($_POST['customer_browser_screen_width']) ? $_POST['customer_browser_screen_width'] : ''; 
		$order->update_meta_data( 'billing_mobile_phone', wc_clean($billing_mobile_phone));
		$order->update_meta_data( 'billing_browser_screen_height', wc_clean($customer_browser_screen_height));
		$order->update_meta_data( 'billing_browser_screen_width', wc_clean($customer_browser_screen_width));

		$order->update_meta_data( '_cb_integration', 'sasop' );
		$order->save();

		// WPML Get current lang by page	

		if ( is_plugin_active( 'sitepress-multilingual-cms/sitepress.php' ) ) {

			$my_current_lang = apply_filters( 'wpml_current_language', NULL );

			// if ( ! add_post_meta(  $order_id , '_cybersource_wpml' , $my_current_lang , true ) ) {
			// 	update_post_meta ( $order_id, '_cybersource_wpml' , $my_current_lang );
			// }

			$order->update_meta_data( '_cybersource_wpml', $my_current_lang );
			$order->save();
			
		} else {
			//update_post_meta ( $order_id, '_cybersource_wpml' , "" );
			$order->update_meta_data( '_cybersource_wpml', "" );
			$order->save();
		}

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

			parent::cybersource_custom_validate_address_fields();
			$this->validate_address_fields($order_id);
			
		}


		// create transaction UUID
		$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();

		$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 validate_address_fields($order_id){

		global $woocommerce;

    	$order = wc_get_order( $order_id );
		
		// Billing Fields Validate

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

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

			
		}

		// Shipping 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 ){
			if( $this->enable_auto_split_address === false ){
				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 ){
			if( $this->enable_auto_split_address === false ){
				wc_add_notice( __( sprintf( "Error when processing payment: '%s'", "Invalid Shipping Address 2 Maximum Character Length Exceeded!" ) , 'woocommerce'), "error" );
				return false;
			}
		}

	}


    public function clean_cards_data( $order_id ){

		if( WC()->session->get( $this->id. '_' .$order_id. '_card_number' ) ){
			WC()->session->set( $this->id. '_' .$order_id. '_card_number' , '' );
		}
		
		if( WC()->session->get( $this->id. '_' .$order_id. '_card_cvc' ) ){
			WC()->session->set( $this->id. '_' .$order_id. '_card_cvc' , '' );
		}
		
		if( WC()->session->get( $this->id. '_' .$order_id. '_card_exp_year' )) {
			WC()->session->set( $this->id. '_' .$order_id. '_card_exp_year' , '' );
		}

		if( WC()->session->get( $this->id. '_' .$order_id. '_fingerprint_uid' )) {
			WC()->session->set( $this->id. '_' .$order_id. '_fingerprint_uid' , '' );
		}

		if( WC()->session->get( $this->id. '_' .$order_id. '_payment_token' )) {
			WC()->session->set( $this->id. '_' .$order_id. '_payment_token' , '' );
		}

		if( WC()->session->get( $this->id. '_' .$order_id. '_save_token' )) {
			WC()->session->set( $this->id. '_' .$order_id. '_save_token' , '' );
		}
			
	}

	//* Function to check if the card is an Amex card
	public function is_amex_card($card_number) {
		return preg_match('/^3[47][0-9]{13}$/', $card_number);
	}

	public function is_visa_or_mastercard($card_number) {
		return preg_match('/^(4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$/', $card_number);
	}

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

		//Validate the billing fields

		$created_via = $order->get_created_via();

		if($created_via == "admin" ){
			// Clean Session CC Data
    		if( WC()->session->get( $this->id. '_' .$order_id. '_payment_token' )) {
				WC()->session->set( $this->id. '_' .$order_id. '_payment_token' , '' );
			}
		} 

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

			if($this->validate_address_fields($order_id) === false ){
				if($created_via == "admin" ){
					wp_redirect( $order->get_checkout_payment_url() );
				} else {
					wp_redirect( wc_get_checkout_url() );
				}
				
			};

		}

		// 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;		
		}

		if( $this->line_items == 'yes' ){

			// Get Cart Items
			$cart_items = $woocommerce->cart->get_cart();

			$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']);
						
					}

					$units_of_measurement = !empty($this->settings['units_of_measurement']) ? $this->settings['units_of_measurement'] : '';
					$item_commodity_code = !empty($this->settings['item_commodity_code']) ? $this->settings['item_commodity_code'] : ''; 
					
					$_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;


					$processing_level = $this->processing_level;
					

					if( $processing_level !== 'none' ){

						$cb_sf_line_times['item_'.$x.'_invoice_number'] 		= $order->get_order_number();
						

						if(!empty($units_of_measurement)){
							$cb_sf_line_times[ 'item_'.$x.'_unit_of_measure'] = $units_of_measurement;
						}

						if(!empty($item_commodity_code)){
							$cb_sf_line_times['item_'.$x.'_commodity_code'] = $item_commodity_code;
						}
						
						$cb_sf_line_times['item_'.$x.'_tax_amount'] = (double) 0;

					} 

					$cb_sf_line_times['line_item_count'] 		= count($cart_items);

					$x++;
				}
			}

		}

		
		

		// Get Configuration before redirect to cybersource

		$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;

		if(WC()->session->get( $this->id. '_' .$order_id. '_save_token' ) == 1 ){
			$transaction_type  = "sale,create_payment_token";

		// 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();
		
		} else {
			$transaction_type  = $this->trans_type_sop;
		}


		$payment_token  = sanitize_text_field(WC()->session->get( $this->id. '_' .$order_id. '_payment_token' ));
		$card_number 	= sanitize_text_field(WC()->session->get( $this->id. '_' .$order_id. '_card_number' ));
		$card_cvc 		= sanitize_text_field(WC()->session->get( $this->id. '_' .$order_id. '_card_cvc' ));
		$card_exp_year 	= sanitize_text_field(WC()->session->get( $this->id. '_' .$order_id. '_card_exp_year' ));			

		//$payment_token = "";
		
		$signed_field_names = explode( ',', $signed_field_names );

		// Remove the fields for AMEX card level 3 processing

		if($this->is_visa_or_mastercard($card_number)){
		}else{

			$level3_fields_data = array(
				'duty_amount',
				'discount_amount',
				'purchasing_level',
				'ship_from_postal_code',
				'user_po'
			);

			// Unset the keys
			foreach ($level3_fields_data as $key) {
				if (($key_index = array_search($key, $signed_field_names)) !== false) {
					unset($signed_field_names[$key_index]);
				}
			}
			
		} 

		

		if(!empty($payment_token)){

			$card_inputs = array(
				'card_type',
				'card_number',
				'card_expiry_date',
				'card_cvn',
				'payment_method'

			);
			//signed_field_names
			foreach( $signed_field_names as $key => $value ){
				if(in_array( $value, $card_inputs)){
					unset($signed_field_names[$key]);
				}
			}

			// unsigned_field_names
			if(!empty($unsigned_field_names)){

				$unsigned_field_names = explode( ',', $unsigned_field_names );

				foreach( $unsigned_field_names as $key => $value ){
					if(in_array( $value, $card_inputs)){
						unset($unsigned_field_names[$key]);
					}
				}

				$unsigned_field_names = implode(',', $unsigned_field_names);	
	
			}

		} else {

			$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 processing your payment...' , '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
			do_action( 'cybersource_device_fingerprint_profiler' );
		?>
	   
	   <?php 

	   	$consumer_id = $order->get_customer_id();

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

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

		// Defaults Address	
		$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_shipping_address1 = sanitize_text_field($this->strip_extra_char($order->get_shipping_address_1()));
		$get_shipping_address2 = sanitize_text_field($this->strip_extra_char($order->get_shipping_address_2()));

		if( $this->enable_auto_split_address === true ){
			$addres_max_length = ! empty($this->address_input_size) ? $this->address_input_size : 41;

			if( ! empty($get_billing_address_1) && strlen($get_billing_address_1) > $addres_max_length ){

				$split_billing_address		= str_split($get_billing_address_1,$addres_max_length);
				$get_billing_address_1    	= $split_billing_address[0];  		
				
				if(empty($get_billing_address_2)){
					$get_billing_address_2 	= $split_billing_address[1];
				} else {
					$get_billing_address_2 	= $split_billing_address[1] . " ". $get_billing_address_2;
					// if $get_billing_address_2 > $addres_max_length the validation is on the cybersource
				}

			}

			

			if( ! empty($get_shipping_address1) && strlen($get_shipping_address1) > $addres_max_length ){

				$split_shipping_address		= str_split($get_shipping_address1,$addres_max_length);
				$get_shipping_address1    	= $split_shipping_address[0];  		
				
				if(empty($get_shipping_address2)){
					$get_shipping_address2 	= $split_shipping_address[1];
				} else {
					$get_shipping_address2 	= $split_shipping_address[1] . " ". $get_shipping_address2;
					// if $get_shipping_address2 > $addres_max_length the validation is on the cybersource
				}

			}
		}

		// 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(" ","",sanitize_text_field($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'				=> sanitize_text_field($this->strip_extra_char($order->get_billing_city())),
		  'bill_to_address_city'	=> sanitize_text_field($this->strip_extra_char($order->get_billing_city())),
		  'bill_to_address_country'	=> sanitize_text_field($order->get_billing_country()),
		  'bill_address1'			=> sanitize_text_field($this->strip_extra_char($order->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'=> sanitize_text_field($order->get_billing_postcode()),
		  'bill_to_address_state'	=> sanitize_text_field($this->strip_extra_char($order->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'	=> $get_shipping_address1,
		  'ship_to_address_line2'	=> $get_shipping_address2,
		  'ship_to_address_postal_code'	=> sanitize_text_field($order->get_shipping_postcode()),
		  'ship_to_address_state'	=> sanitize_text_field($this->strip_extra_char($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())),
		  'customer_ip_address'		=> WC_Geolocation::get_ip_address(),
		  'card_type'				=> parent::get_cc_type( $card_number ) ,
		  'card_number'				=> $card_number,
		  'card_expiry_date'		=> $card_exp_year ,
		  'card_cvn'				=> $card_cvc,
		  'payment_method'			=> 'card',
		  'consumer_id'				=> sanitize_text_field($consumer_id),
		  'merchant_id'				=> sanitize_text_field($this->merchant_id),
		  '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')),
				 	
		);

		
		if(!empty($payment_token)){

			unset($cb_args['card_type']);
			unset($cb_args['card_number']);
			unset($cb_args['card_expiry_date']);
			unset($cb_args['card_cvn']);
			unset($cb_args['payment_method']);
			$cb_args['payment_token'] = $payment_token;
		}


		$processing_level = $this->processing_level;

		if( $processing_level !== 'none' ){

			$purchase_level = array(				
				'duty_amount'				=> $amount,
				'discount_amount'			=> $order->get_discount_total(),
				'purchasing_level' 			=> $this->processing_level,
				'ship_from_postal_code'     => $get_billing_postcode,				
				'user_po'					=> $order->get_order_number()				
			);

			if($this->is_visa_or_mastercard($card_number)){
				$cb_args = array_merge($cb_args, $purchase_level);
			} 

			//$cb_args = array_merge($cb_args, $purchase_level);

		}
		

		//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 );
		}

		$cb_signature = array( 'signature' => parent::sign( $cb_args , $secret_key ) );

		$cb_combined_params =  array_merge( $cb_args, $cb_signature);

		parent::log( 'Cybersource Request - SOP API: ' . 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).'" />';
		}	

		// Clean Session CC Data
    	$this->clean_cards_data( $order_id );
		
	   
	   ?>
	   
	    <?php echo implode('', $cb_args_array);
		
		//echo "<pre>"; print_r($cb_args); echo "</pre>";
		//exit;
		
		?>
	   
        <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', 'woocommerce');?></a>
        </form>
    <?php 		


		

		

	}	

	public function cb_form( $order, $cb_args_array, $cb_action_url, $thank_you_redirecting_message ){
	}

	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 = parent::virtual_order_payment_complete_order_status( $order_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 add_payment_method() {
		
		// Get CC POST Data
    	$card_number 		 = wc_clean( $_POST[ $this->id.'-cardnumber'] );
        $card_number 		 = str_replace( ' ', '', $card_number);
        $card_cvc    		 = wc_clean( $_POST[ $this->id.'-card_cvc'] );
		
		$card_exp_year 		 = wc_clean( $_POST[ $this->id.'-expiry_y'] );
		$card_exp_month 		 = wc_clean( $_POST[ $this->id.'-expiry_m'] );
		
		//fix for SOAP-ERROR: Parsing WSDL: Couldn't load 
		libxml_disable_entity_loader(false); 

		// Cybersource Request 
		// http://apps.cybersource.com/library/documentation/dev_guides/CC_Svcs_SO_API/html/wwhelp/wwhimpl/js/html/wwhelp.htm#href=request_fields_so.html
		$soap = $this->soaptoolkit_request(); 
		$temp_orderno = uniqid();
		$request = $soap->createRequest( $temp_orderno );

		$request->clientLibrary 		= "WooCommerce PHP Client";
		$request->clientLibraryVersion 	= phpversion();
		$request->clientEnvironment 	= php_uname();
		$request->merchantID 			= $this->merchant_id;			
		$request->merchantReferenceCode = $temp_orderno;			

		// disable Address Verification Services (AVS)
		$businessRules = new stdClass();

		if( $this->avs === true ){
			$ignore_avs = false;
		} else {
			$ignore_avs = true;
		}

		$businessRules->ignoreAVSResult = $ignore_avs;
		$request->businessRules  = $businessRules;

		// Cybersource CC object
		$card = new stdClass();
		$card->accountNumber 	= sanitize_text_field($card_number);
		$card->expirationMonth 	= sanitize_text_field($card_exp_month);
		$card->expirationYear 	= sanitize_text_field($card_exp_year);

		$cardtype 				= parent::get_cc_type( $card_number );

		if( ! empty( $cardtype ) ){
			$card->cardType 		= $cardtype;	
		}

		$card->cvNumber 	    = $card_cvc;

		$request->card = $card;

		$customer_id = get_current_user_id();
		
		// Cybersource Billing Address Object 
		$billTo = new stdClass();
		$billTo->firstName 	= sanitize_text_field(get_user_meta( $customer_id, 'billing_first_name', true ));
		$billTo->lastName 	= sanitize_text_field(get_user_meta( $customer_id, 'billing_last_name', true ));
		$billTo->street1	= sanitize_text_field(get_user_meta( $customer_id, 'billing_address_1', true ));
		$billTo->street2 	= sanitize_text_field(get_user_meta( $customer_id, 'billing_address_2', true ));
		$billTo->city 		= sanitize_text_field(get_user_meta( $customer_id, 'billing_city', true ));
		$billTo->state 		= sanitize_text_field(get_user_meta( $customer_id, 'billing_state', true ));
		$billTo->postalCode = sanitize_text_field(get_user_meta( $customer_id, 'billing_postcode', true ));
		$billTo->country 	= sanitize_text_field(get_user_meta( $customer_id, 'billing_country', true ));
		$billTo->email 		= sanitize_text_field(get_user_meta( $customer_id, 'billing_email', true ));
		$billTo->company 	= sanitize_text_field(get_user_meta( $customer_id, 'billing_company', true ));
		$billTo->phoneNumber = sanitize_text_field(get_user_meta( $customer_id, 'billing_phone', true ));
		$billTo->ipAddress 	= WC_Geolocation::get_ip_address();
		$request->billTo    = $billTo;

		// Cybersource Shipping Address Object
		$shipTo = new stdClass();
		$shipTo->city 			= sanitize_text_field(get_user_meta( $customer_id, 'shipping_city', true ));
		$shipTo->country 		= sanitize_text_field(get_user_meta( $customer_id, 'shipping_country', true ));
		$shipTo->firstName 		= sanitize_text_field(get_user_meta( $customer_id, 'shipping_first_name', true ));
		$shipTo->lastName 		= sanitize_text_field(get_user_meta( $customer_id, 'shipping_last_name', true ));
		$shipTo->phoneNumber 	= sanitize_text_field(get_user_meta( $customer_id, 'billing_phone', true ));
		$shipTo->postalCode 	= sanitize_text_field(get_user_meta( $customer_id, 'shipping_postcode', true ));
		$shipTo->state 			= sanitize_text_field(get_user_meta( $customer_id, 'shipping_state', true ));
		$shipTo->street1 		= sanitize_text_field(get_user_meta( $customer_id, 'shipping_address_1', true ));
		$shipTo->street2 		= sanitize_text_field(get_user_meta( $customer_id, 'shipping_address_2', true ));
		$request->shipTo    	= $shipTo;	


		// Add Tokenization 
		$recurringSubscriptionInfo = new stdClass();
		$recurringSubscriptionInfo->frequency = 'on-demand';
		$request->recurringSubscriptionInfo = $recurringSubscriptionInfo;

		$paySubscriptionCreateService = new stdClass();
		$paySubscriptionCreateService->run = "true";
		$request->paySubscriptionCreateService = $paySubscriptionCreateService;

		$purchaseTotals 					= new stdClass();
		$purchaseTotals->currency 			= get_woocommerce_currency();
		$request->purchaseTotals 			= $purchaseTotals;

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

		parent::log( 'Cybersource Request - SO: ' . print_r( $request, true ) );
		parent::log( 'Cybersource Response - SO: ' . print_r( $reply, true ) );

		if($reply->decision == 'ACCEPT' ){

			$token = $reply->paySubscriptionCreateReply->subscriptionID;

			if(!empty($token)){

				$set_last4 = substr($card_number,-4);
				$card_type = parent::get_cc_type($card_number);
				switch($card_type){
					case '001':
						$cc_type = __('Visa','woocommerce');
					break;
					case '002':
						$cc_type = __('MasterCard','woocommerce');
					break;
					case '003':
						$cc_type = __('American Express','woocommerce');
					break;
					case '004':
						$cc_type = __('Discover','woocommerce');
					break;
					case '005':
						$cc_type = __('Diners Club','woocommerce');
					break;
					case '014':
						$cc_type = __('EnRoute','woocommerce');
					break;
					case '007':
						$cc_type = __('JCB','woocommerce');
					break;
					case '024':
						$cc_type = __('Maestro', 'woocommerce');
					break;
					case '033':
						$cc_type = __('Visa Electron','woocommerce');
					break;
					case '035':
						$cc_type = __('Laser','woocommerce');
					break;
					case '006':
						$cc_type = __('Carte Blanche','woocommerce');
					break;
					case '034':
						$cc_type = __('Dankort','woocommerce');
					break;
					default:
						$cc_type = __('unknown','woocommerce');
					break;
				}

				$card_token[ 'token' ] 				= sanitize_text_field($token);
				$card_token[ 'card_type' ] 			= sanitize_text_field($cc_type);
				$card_token[ 'set_last4' ]			= sanitize_text_field($set_last4);
				$card_token[ 'set_expiry_month' ]	= sanitize_text_field($card_exp_month);
				$card_token[ 'set_expiry_year' ]	= sanitize_text_field($card_exp_year);

				//* Fire save card token
				$ret = $this->save_card_token($card_token);

			}

		} else {

			wc_add_notice( __( $this->reason_code( $reply->reasonCode ) , 'woocommerce' ), 'error' );
		  	return;

		}

		
		
		if ( is_null( $ret ) ) {
		  wc_add_notice( __( 'There was a problem adding this card.', 'woocommerce' ), 'error' );
		  return;
		}
			
		return array(
		  'result'   => 'success',
		  'redirect' => wc_get_endpoint_url( 'payment-methods' ),
		);
	}

	public function save_card_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() );
		}

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

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

	}

	public function get_customer_token( $id ){

		$ret = '';

		if( !empty($id)){
			$customer_token = WC_Payment_Tokens::get( $id );
			$ret = $customer_token->get_token();
		} 

		return $ret;
	}

	public function capture_order_status_completed( $order_id, $order ){


		if( $this->transaction_type == 'sale' ) return;

		$order = wc_get_order( $order_id );
		$transaction_id = $order->get_meta( '_'. $this->id .'_transaction_id' );
		$request_token = $order->get_meta(  '_'. $this->id .'_request_token' );

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

		
		if ( ! $transaction_id ) {
			return new WP_Error( $this->id . '_capture_error',
				esc_html__( sprintf(
					'%s Capture failed because the Request ID is missing.',
					ucwords($this->id)
				), 'woocommerce' )
			);
		}

		$soap = $this->soaptoolkit_request(); 
		$request = $soap->createRequest( $order->get_currency());
		
		$request->clientLibrary 		= "WooCommerce PHP Client";
		$request->clientLibraryVersion 	= phpversion();
		$request->clientEnvironment 	= php_uname();
		$request->merchantID 			= $this->merchant_id;			
		$request->merchantReferenceCode = $order_id;


		if( !empty($transaction_id) && !empty($request_token)  ){

				$capture_service = new stdClass();
				$capture_service->run = 'true';
				$capture_service->authRequestToken = $request_token;

				if ( isset( $transaction_id ) )
				{
					$capture_service->authRequestID = $transaction_id;
				}

				$request->ccCaptureService = $capture_service;	
				$request->purchaseTotals = (object) array( 'grandTotalAmount' => (double) number_format( $amount, 2, ".", "") );			
				
				parent::log( 'Cybersource Request - SOP: ' . print_r( $request, true ) );

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

				parent::log( 'Cybersource Response - SOP: ' . print_r( $response, true ) );

				if(!empty($response->requestID) && $response->reasonCode == 100 && $response->decision == 'ACCEPT' ){

					$request_ID 	= $response->requestID; 
					$request_token  = $response->requestToken; 
					// update_post_meta( $order_id, '_' . $this->id . '_capture_request_id', $request_ID );
					// update_post_meta( $order_id, '_' . $this->id . '_request_token', $request_token );
					// update_post_meta( $order_id, '_' . $this->id . '_capture', 1 );

					$order->update_meta_data( '_' . $this->id . '_capture_request_id', $request_ID );
					$order->update_meta_data( '_' . $this->id . '_request_token', $request_token );
					$order->update_meta_data(  '_' . $this->id . '_capture', 1 );
					$order->save();
					
					$order->add_order_note(
						esc_html__( sprintf(
							'%1$s Capture %2$s with Request ID of %3$s',
							$this->method_title,
							sanitize_text_field($response->decision),
							sanitize_text_field($response->requestID)
						), 'woocommerce' )
					);

					return true;

				} else {

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

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

				}
				return false;
		
		}
		return $response;
	}

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

		if( $this->transaction_type == 'authorization' ){
			return parent::reversal_payment ( $order_id, $amount = null, $reason = '' );
		} else {
			return parent::void_payment ( $order_id, $amount = null, $reason = '' );
		}
		
	}

}