<?php
/***************************************************************************
 *                                                                          *
 * Copyright (c) 2005 ISPG Technologies (I) Pvt Ltd. All rights reserved.   *
 *                                                                          *
 * This  is  commercial  software,  only  users  who have purchased a valid *
 * license  and  accept  to the terms of the  License Agreement can install *
 * and use this program.                                                    *
 *                                                                          *
 ****************************************************************************
 * PLEASE READ THE FULL TEXT  OF THE SOFTWARE  LICENSE   AGREEMENT  IN  THE *
 * "copyright.txt" FILE PROVIDED WITH THIS DISTRIBUTION PACKAGE.            *
 ****************************************************************************/
//
//$Id: PxfusionModel.php, v 1.0 2011/06/14 20:52:11

//
class PxfusionModel extends PaymentModel
{
	// DPS Px Fusion Details
	protected $fusion_username ;
	protected $fusion_password ;
	protected $wsdl ;
	// Variables/Objects that are used to hold data for transactions
	public $tranDetail;
	protected $soap_client;
	public function __construct()
	{
		parent::__construct();
		if ( ! is_object($this->tranDetail))
		{
			$this->tranDetail = new stdClass();
		}
	}
	public function set_txn_detail($property, $value)
	{
		$this->tranDetail->$property = $value;
	}
	public function get_transaction_id()
	{
		$this->soap_client = new SoapClient($this->wsdl, array('soap_version' => SOAP_1_1));
		// SoapClient does some magic conversion from array into the required soap+xml format
		$array_for_soap = array(
			'username' => $this->fusion_username,
			'password' => $this->fusion_password,
			'tranDetail' => get_object_vars($this->tranDetail) # extracts all properties of object into associative array
		);
		$response = $this->soap_client->GetTransactionId($array_for_soap);
		return $response;
	}

	public function get_transaction($transaction_id,$paymentSettingsGroupID=0)
	{
		parent::listPaymentSettingsValues($paymentSettingsGroupID);
        $this->wsdl            = $this->settingsVars["payment_gateway_url"];
        $this->fusion_username = $this->settingsVars["post_username"];
        $this->fusion_password = $this->settingsVars["post_password"];
		$this->soap_client = new SoapClient($this->wsdl, array('soap_version' => SOAP_1_1));
		$array_for_soap = array(
			'username' => $this->fusion_username,
			'password' => $this->fusion_password,
			'transactionId' => $transaction_id
		);
		$response = $this->soap_client->GetTransaction($array_for_soap);
		return $response;
	}
	//Function to Process to orders		
    public function process($order = '',$orderItems = '')
    {
		$ObjCurrency		  	= new CurrencyModel();
		parent::listPaymentSettingsValues($order['paymentSettingsGroupID']);
        $this->wsdl            	= $this->settingsVars["payment_gateway_url"];
        $this->fusion_username 	= $this->settingsVars["post_username"];
        $this->fusion_password 	= $this->settingsVars["post_password"];
		$purchaseUrl		   	= $this->settingsVars["payment_gateway_purchase_url"];
        $returnUrl 				= $order['returnURL'];
		$payAmount            	= $order['orderTotalAmount'];
        $paymentCurrency      	= $this->settingsVars["payment_currency"];
        $currencyArr          	= '';
		
		if ($paymentCurrency != '')
		{
			$paymentCurrency = str_replace(", ", ",", $paymentCurrency);
			$currencyArr     = explode(",", $paymentCurrency);
		}
		if(count($currencyArr)<1)
		{
			$this->isError 		= true;
			$this->errorMessage	= "Currency not configured , Please contact the site admin";
			return false;
		}
		else
		{
			$currencyFlag = false;
			$purchasedCurrencyDetails 	= $ObjCurrency->getCurrencyByCurrencyID($order["purchasedCurrency"]);
			$currencyCode				= $purchasedCurrencyDetails['currencyCode'];
			$systemCurrencies 			=	$ObjCurrency->listCurrencyCodes();
			if(!in_array($purchasedCurrencyDetails['currencyCode'],$currencyArr))
			{
				foreach ($systemCurrencies as $key => $currency)
				{
					if(in_array($currency['currencyCode'],$currencyArr))
					{
						$currencyFlag = true;
						$supportedCurrencyCode 	= $currency['currencyCode'];	
						$supportedCurrencyID 	= $currency['currencyID'];
						break;
					}
				}
				if($currencyFlag==true)
				{
					$payAmount = $ObjCurrency->convertValueCustom($payAmount,$order["purchasedCurrency"],$supportedCurrencyID);
					$currencyCode		=	$supportedCurrencyCode;
				}
				else
				{
					$this->isError 		= true;
					$this->errorMessage	= "Currency not configured , Please contact the site admin";
					return false;
				}
				
			}
		}
       
        $userPayAmount  = number_format($payAmount, 2, ".", "");
		// Set some transaction details
		if ($order['authValue'] == 'Authorization') {
            $txnType = 'Auth';
        } else {
            $txnType = 'Purchase';
        }
		$txtInvDesc     = "Payment From " . $order['postData']."(ORD- ".$order['masterOrderID'].")";
		$txtInvDesc     = substr($txtInvDesc, 0, 90);
		$this->set_txn_detail('txnType', $txnType);	# required
		$this->set_txn_detail('currency', $currencyCode);		# required
		$this->set_txn_detail('returnUrl', $returnUrl);	# required
		$this->set_txn_detail('amount', $userPayAmount);		# required
		$this->set_txn_detail('merchantReference', $txtInvDesc);
		// Some of the many optional settings that could be specified:
		$this->set_txn_detail('enableAddBillCard', 0);
		$this->set_txn_detail('txnRef', substr(uniqid() . rand(1000,9999), 0, 16)); # random 16 digit reference);
		// Make the request for a transaction id
		$response = $this->get_transaction_id();
		if (!$response->GetTransactionIdResult->success)
		{
		$this->isError      = true;
        $this->errorMessage = "There was a problem getting a transaction id from DPS.";
        return false;
		}
		else
		{
		$transaction_id = $response->GetTransactionIdResult->transactionId;
		$session_id = $response->GetTransactionIdResult->sessionId;
		$this->processCurl($order,$transaction_id,$session_id,$purchaseUrl);
		}

    }
    //End of function
	//creating curl for pass to the payment gateway
	public function processCurl($order,$transaction_id,$session_id,$purchaseUrl)
    {
	//set POST variables
	$fields = array(
						'SessionId'=>urlencode($session_id),
						'Action'=>'Add',
						'Object'=>'DpsPxPay',
						'CardNumber'=>urlencode($order['postData']["creditCardNumber"]),
						'ExpiryMonth'=>urlencode($order['postData']["expMonth"]),
						'ExpiryYear'=>urlencode(substr($order['postData']["expYear"], -2)),
						'Cvc2'=>urlencode($order['postData']["securityCode"]),
						'CardHolderName'=>urlencode($order['postData']["creditCardFirstName"]),
						'CardHolderName'=>urlencode($order['postData']["creditCardFirstName"])
				);
		echo "<html>\n";
		echo "<head><title>Processing Payment...</title></head>\n";
		echo "<body >\n";
		echo "<center><h3>Please wait, your order is being processed...</h3></center>\n";
		echo "<form enctype='multipart/form-data' name=\"frmsendpaymentrequest\" method=\"post\" action=\"".$purchaseUrl."\">\n";
		foreach ($fields as $name => $value) 
		{
			echo "<input type=\"hidden\" name=\"$name\" value=\"$value\">";
      	}
		echo "<input type=\"hidden\" value=\"$transaction_id\">";
      	echo "</form>\n";
      	echo "</body></html>\n";
		echo "<script>document.frmsendpaymentrequest.submit();</script>";
		exit;
    }
	
	 public function processCustom($order = '')
    {
		$ObjCurrency			= new CurrencyModel();
        parent::listPaymentSettingsValues($order['paymentSettingsGroupID']);
		$getPaymentTransactionDetails = parent::getPaymentTransactionDetails(0,
		$order["masterOrderID"]);
		$purchasedCurrencyDetails = $ObjCurrency->getCurrencyByCurrencyID(
		$getPaymentTransactionDetails["paymentCurrencyID"]);
		$currencyCode			= $purchasedCurrencyDetails['currencyCode'];
        $this->isError         = false;
        //check is transaction completed
        if ($order["paymentType"] != "AUTH_ONLY" || $order["paymentStatus"] == 'Received') {
            $this->isError      = true;
            $this->errorMessage = "Transaction already completed";
            return false;
        }
        //get captured total amount & x_trans_id
        $capturedTotalAmount = $getPaymentTransactionDetails["convertedPaymentAmount"];
		
        $payAmount           = number_format($capturedTotalAmount, 2, ".", "");
        $transactionID       = $order["transactionID"];
        $dpsTxnRef           = $getPaymentTransactionDetails['transactionID'];
        $cmdDoTxnTransaction = '';
        $cmdDoTxnTransaction .= "<Txn>";
        $cmdDoTxnTransaction .= "<PostUsername>" . 
		$this->settingsVars["post_username"] . "</PostUsername>"; #Insert your DPS Username here
        $cmdDoTxnTransaction .= "<PostPassword>" . 
		$this->settingsVars["post_password"] . "</PostPassword>"; #Insert your DPS Password here
        $cmdDoTxnTransaction .= "<Amount>" . $payAmount . "</Amount>";
        $cmdDoTxnTransaction .= "<InputCurrency>" . $currencyCode . "</InputCurrency>";
        $cmdDoTxnTransaction .= "<DpsTxnRef>" . $dpsTxnRef . "</DpsTxnRef>";
        $cmdDoTxnTransaction .= "<TxnType>Complete</TxnType>";
        $cmdDoTxnTransaction .= "</Txn>";
        $url = "sec.paymentexpress.com/pxpost.aspx";
        $ch  = curl_init();
        curl_setopt($ch, CURLOPT_URL, "https://" . $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "Content-Type: text/xml"
        ));
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $cmdDoTxnTransaction);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //Needs to be included if no *.crt is available to verify SSL certificates
        curl_setopt($ch, CURLOPT_SSLVERSION, 3);
        $result = curl_exec($ch);
        curl_close($ch);
        $params     = $this->parseXml($result);
        $paramstore = serialize($params);
		$responseText    = $params[TXN][HELPTEXT];
        $success    = $params[TXN][SUCCESS];
        if ($success == '1') {
            $paymentGatewayCharge               = '';
            $paymentMethodName                  = $this->settingsVars["payment_method_name"];
            $order['orderStatus']               = 'Completed';
            parent::createTransaction($order, $transactionID, 
			"ORDER TYPE: PRIOR_AUTH_CAPTURE\n\n: Success", $paramstore, 
			"AUTH_CAPTURE", $paymentGatewayCharge, $paymentMethodName,
			$getPaymentTransactionDetails["paymentCurrencyID"],$payAmount);
            $this->isError      = false;
            $this->errorMessage = "";
            return "Success";
        } else {
            $this->isError      = true;
            $this->errorMessage = $responseText;
        }
        if ($this->isError) {
            $this->logStart();
            $this->log($result, $this->settingsVars["payment_processor_id"]);
            $$this->logFinish();
            $this->isError = true;
        }
        return !$this->isError;
    }
	
	public function processRefund($order = '', $postValues = '')//payment refunding process
    {
        //$ObjPayment = new PaymentModel();
        $ObjRefund  = new RefundModel();
        $paySetGroupKey       = $this->getPaymentSettingGroupByGroupKey('payment_express_post');
        $paymentSettingsValue = $this->listPaymentSettingsValues($paySetGroupKey);
        $dpsTxnRef  = urlencode($postValues['apiPaymentTransactionID']);
        $merchRef   = $postValues['orderNumber'];
        $refundAmt  = number_format($order['orderTotalAmount'], 2, ".", "");
        $txnType    = 'Refund';
        $postUrl    = "https://sec.paymentexpress.com/pxpost.aspx";
        $postXml    = "<Txn>
							<PostUsername>" . $paymentSettingsValue->settingsVars["post_username"] . "</PostUsername>
							<PostPassword>" . $paymentSettingsValue->settingsVars["post_password"] . "</PostPassword>
							<Amount>" . $refundAmt . "</Amount>
							<TxnType>" . $txnType . "</TxnType>
							<DpsTxnRef>" . $dpsTxnRef . "</DpsTxnRef>
							<MerchantReference>" . $merchRef . "</MerchantReference>
						</Txn>";
        $ch         = curl_init();
        curl_setopt($ch, CURLOPT_URL, $postUrl);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "Content-Type: text/xml"
        ));
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postXml);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //Needs to be included if no *.crt is available to verify SSL certificates
        curl_setopt($ch, CURLOPT_SSLVERSION, 3);
        $result 	= curl_exec($ch);
        curl_close($ch);
        $params              = $this->parseXml($result);
        $pxResponse          = 'RESPONSETEXT=' . $params[TXN][RESPONSETEXT] . '<br/>HELPTEXT=' . $params[TXN][HELPTEXT] . '<br/>DPSTXNREF=' . $params[TXN][DPSTXNREF];
        $success             = $params[TXN][SUCCESS];
        $masterOrderID       = $postValues['masterOrderID'];
        $refundTransactionID = $postValues['keyRefundTransactionID'];
        if ($success == '1') {
            $arrXnResponse['transactionID']  = $params[TXN][DPSTXNREF];
            $arrXnResponse['refundResponse'] = $pxResponse;
            $arrXnResponse['refundAmount']   = $params[TXN][1][AMOUNT];
            $resUpdateRefund                 = $ObjRefund->updateRefundTransaction('', $refundTransactionID, $arrXnResponse, $masterOrderID);
            $this->isError                   = false;
            $this->errorMessage              = "";
        } else {
            $arrXnResponse['transactionID']  = '';
            $arrXnResponse['refundResponse'] = $pxResponse;
            $arrXnResponse['refundAmount']   = '';
            $resUpdateRefund                 = $ObjRefund->updateRefundTransaction('', $refundTransactionID, $arrXnResponse, $masterOrderID);
            $this->isError                   = true;
            $this->errorMessage              = $ResponseText;
        }
        return !$this->isError;
    }
	
	public function parseXml($data)
    {
        $xmlParser = xml_parser_create();
        xml_parse_into_struct($xmlParser, $data, $vals, $index);
        xml_parser_free($xmlParser);
        $params = array();
        $level  = array();
        foreach ($vals as $xmlElem) {
            if ($xmlElem['type'] == 'open') {
                if (array_key_exists('attributes', $xmlElem)) {
                    list($level[$xmlElem['level']], $extra) = array_values($xmlElem['attributes']);
                } else {
                    $level[$xmlElem['level']] = $xmlElem['tag'];
                }
            }
            if ($xmlElem['type'] == 'complete') {
                $startLevel = 1;
                $phpStmt    = '$params';
                
                while ($startLevel < $xmlElem['level']) {
                    $phpStmt .= '[$level[' . $startLevel . ']]';
                    $startLevel++;
                }
                $phpStmt .= '[$xmlElem[\'tag\']] = $xmlElem[\'value\'];';
                eval($phpStmt);
            }
        }
        return $params;
    }
}