<?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: PxpaycurlModel.php, v 1.0 2011/06/14 20:52:11
//
class PxpaycurlModel extends PaymentModel
{
    var $PxPayKey;
    var $PxPayUrl;
    var $PxPayUserid;
    public function process($order = '',$orderItems = '')//payment collection processing
    {
		$ObjCurrency		  = new CurrencyModel();
		parent::listPaymentSettingsValues($order['paymentSettingsGroupID']);
		$key                     = $this->settingsVars["pay_key"];
        $url                     = $this->settingsVars["payment_gateway_url"];
        $userId                  = $this->settingsVars["pay_userid"];
        $this->PxPayKey          = $key;
        $this->PxPayUrl          = $url;
        $this->PxPayUserid       = $userId;
        $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;
				}
				
			}
		}
		
		if($payAmount<.01)
		{
			$this->isError 		= true;
			$this->errorMessage	= "Invalid amount , please use another method";
			return false;
		}
		        
        $billingAddress1 = ($order['billingAddress']['billingAddress1'] != '') ? $order['billingAddress']['billingAddress1'] : '';
        /* Payment Express Process */
        $httpHost        = getenv("HTTP_HOST");
        $requestUri      = getenv("SCRIPT_NAME");
        $serverUrl       = "http://$httpHost";
        $scriptUrl       = (version_compare(PHP_VERSION, "4.3.4", ">=")) ? "$serverUrl$requestUri" : "$serverUrl/$requestUri";
        $TxnId           = uniqid("ID");
        $amountInput     = number_format($payAmount, 2, ".", "");	
        if ($order['authValue'] == 'Authorization') {
            $txnTypes = 'Auth';
        } else {
            $txnTypes = 'Purchase';
        }
		$txtInvDesc     = "Payment From " . $order['postData']['creditCardFirstName'] ."(ORD- ".$order['masterOrderID'].")";
        $request = new PxPayRequest();
        $request->setMerchantReference($txtInvDesc);
        $request->setAmountInput($amountInput);
		if($order['orderNumber']>0)
		{
			$request->setTxnData1($order['orderNumber']);
		}
		else
		{
			$request->setTxnData1($order['masterOrderID']);
		}		
        $request->setTxnType($txnTypes);
        $request->setCurrencyInput($currencyCode);
        $request->setEmailAddress($order['billingAddress']['billingEmail']);
        $request->setUrlFail($order['cancelURL']); # can be a dedicated failure page
        $request->setUrlSuccess($order['returnURL']); # can be a dedicated success page
        if($order['orderNumber']>0)
		{
			$request->setTxnId($order['orderNumber']);
		}
		else
		{
			$request->setTxnId($order['masterOrderID']);
		}
        #Call makeRequest function to obtain input XML
		//echo '<pre>';print_r($order);print_r($request);exit;
        $requestString = $this->makeRequest($request);
        #Parse output XML
        $response      = new MifMessage($requestString);
        #Parse output XML
        $url           = $response->getElementText("URI");
        $valid         = $response->getAttribute("valid");
		echo $url;
		header("Location: $url");
		exit;
    }

    public function processCustom($order = '')//completing auth only transactions
    {
		$ObjCurrency			= new CurrencyModel();
        $getPaymentTransactionDetails = parent::getPaymentTransactionDetails(0,$order["masterOrderID"]);
		parent::listPaymentSettingsValues($order['paymentSettingsGroupID']);
		$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
		$payAmount 			= $getPaymentTransactionDetails['convertedPaymentAmount'];
        $payAmount           = number_format($payAmount, 2, ".", "");
        $transactionID       = $order["transactionID"];
        $paymentResponse     = unserialize($getPaymentTransactionDetails['extra']);
        $dpsTxnRef           = ($paymentResponse['DpsTxnRef'] == '') ? $DpsTxnRef : $paymentResponse['DpsTxnRef'];
        $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 = "https://sec.paymentexpress.com/pxpost.aspx";
        $ch  = curl_init();
        curl_setopt($ch, CURLOPT_URL, $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);
        $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", 0, $paymentMethodName,
			$getPaymentTransactionDetails["paymentCurrencyID"],$payAmount);
            $this->isError      = false;
            $this->errorMessage = "";
            return "Success";
            
        } else {
            $this->isError      = true;
            $this->errorMessage = "";
        }
        if ($this->isError) 
		{
            $this->logStart();
           	$this->log($result, $ObjPayment->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();
		$ObjCurrency	 = new CurrencyModel();
        $pxPay      	= $ObjPayment->listPaymentSettingsValues($postValues['paymentSettingsGroupID']);
        //$dpsTxnRef  = urlencode($postValues['apiPaymentTransactionID']);
		
		$getPaymentTransactionDetails = parent::getPaymentTransactionDetails(0,$order["masterOrderID"]);
		
		$paymentResponse     = unserialize($getPaymentTransactionDetails['extra']);
        $dpsTxnRef           = ($paymentResponse['DpsTxnRef'] == '') ? $DpsTxnRef : $paymentResponse['DpsTxnRef'];
		
        $merchRef   = $order['orderNumber'];
        $refundAmt  = number_format($order['orderTotalAmount'], 2, ".", "");
		
		
		$supportedCurrencyID = $order["purchasedCurrency"];
		$paymentCurrency	 = $pxPay->settingsVars["payment_currency"];
		
		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)
				{
					$refundAmt = $ObjCurrency->convertValueCustom($refundAmt,$order["purchasedCurrency"],$supportedCurrencyID);
				}
				else
				{
					$this->isError 		= true;
					$this->errorMessage	= "Currency not configured , Please contact the site admin";
					//return false;
				}
				
			}
		}
		
		$refundAmt  = number_format($refundAmt, 2, ".", "");
		
        $txnType    = 'Refund';
        $postUrl    = "https://sec.paymentexpress.com/pxpost.aspx";
        $postXml    = "<Txn>
							<PostUsername>" . $pxPay->settingsVars["post_username"] . "</PostUsername>
							<PostPassword>" . $pxPay->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;
    }
    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;
    }
    #******************************************************************************
    # Create a request for the PxPay interface
    #******************************************************************************
    function makeRequest($request)
    {
        #Validate the Request
        if ($request->validData() == false)
            return "";
        $request->setUserId($this->PxPayUserid);
        $request->setKey($this->PxPayKey);
        $xml    = $request->toXml();
        $result = $this->submitXml($xml);
        return $result;
        
    }
    
    #******************************************************************************
    # Return the transaction outcome details
    #******************************************************************************
    function getResponse($result)
    {
		$paymentSettingsGroupID	=	parent::getPaymentSettingGroupByGroupKey('payment_express');
		parent::listPaymentSettingsValues($paymentSettingsGroupID);
		$key                     = $this->settingsVars["pay_key"];
        $userId                  = $this->settingsVars["pay_userid"];
        $url                     = $this->settingsVars["payment_gateway_url"];
        $this->PxPayKey          = $key;
        $this->PxPayUrl          = $url;
        $this->PxPayUserid       = $userId;
        $inputXml  = "<ProcessResponse><PxPayUserId>" . $userId . "</PxPayUserId><PxPayKey>" . $key . "</PxPayKey><Response>" . $result . "</Response></ProcessResponse>";
		$outputXml = $this->submitXml($inputXml);
        $pxresp    = new PxPayResponse($outputXml);
        return $pxresp;
    }
    
    #******************************************************************************
    # Actual submission of XML using cURL. Returns output XML
    #******************************************************************************
    function submitXml($inputXml)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->PxPayUrl);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $inputXml);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        #set up proxy, this may change depending on ISP, please contact your ISP to get the correct cURL settings
        #curl_setopt($ch,CURLOPT_PROXY , "proxy:8080");
        #curl_setopt($ch,CURLOPT_PROXYUSERPWD,"username:password");
        $outputXml = curl_exec($ch);
        curl_close($ch);
        return $outputXml;
    }
}

class MifMessage
{
    var $xml_;
    var $xml_index_;
    var $xml_value_;
    # Constructor:
    # Create a MifMessage with the specified XML text.
    # The constructor returns a null object if there is a parsing error.
    function MifMessage($xml)
    {
        $p = xml_parser_create();
        xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
        $ok = xml_parse_into_struct($p, $xml, $value, $index);
        xml_parser_free($p);
        if ($ok) {
            $this->xml_       = $xml;
            $this->xml_value_ = $value;
            $this->xml_index_ = $index;
        }
    }
    # Return the value of the specified top-level attribute.
    # This method can only return attributes of the root element.
    # If the attribute is not found, return "".
    function getAttribute($attribute)
    {
        $attributes = $this->xml_value_[0]["attributes"];
        return $attributes[$attribute];
    }
    
    # Return the text of the specified element.
    # The element is given as a simplified XPath-like name.
    # For example, "Link/ServerOk" refers to the ServerOk element
    # nested in the Link element (nested in the root element).
    # If the element is not found, return "".
    function getElementText($element)
    {
        $index = $this->getElementIndex($element, 0);
        if ($index == 0) {
            return "";
        } else {
            #When element existent but empty
            $elementObj = $this->xml_value_[$index];
            if (!array_key_exists("value", $elementObj))
                return "";
            return $this->xml_value_[$index]["value"];
        }
    }
    
    # (internal method)
    # Return the index of the specified element,
    # relative to some given root element index.
    #
    function getElementIndex($element, $rootindex = 0)
    {
        #$element = strtoupper($element);
        $pos = strpos($element, "/");
        if ($pos !== false) {
            # element contains '/': find first part
            $startPath  = substr($element, 0, $pos);
            $remainPath = substr($element, $pos + 1);
            $index       = $this->getElementIndex($startPath, $rootindex);
            if ($index == 0) {
                # couldn't find first part give up.
                return 0;
            }
            # recursively find rest
            return $this->getElementIndex($remainPath, $index);
        } else {
            # search from the parent across all its children
            # i.e. until we get the parent's close tag.
            $level = $this->xml_value_[$rootindex]["level"];
            if ($this->xml_value_[$rootindex]["type"] == "complete") {
                return 0; # no children
            }
            $index = $rootindex + 1;
            while ($index < count($this->xml_value_) && !($this->xml_value_[$index]["level"] == $level && $this->xml_value_[$index]["type"] == "close")) {
                # if one below parent and tag matches, bingo
                if ($this->xml_value_[$index]["level"] == $level + 1 && $this->xml_value_[$index]["tag"] == $element) {
                    return $index;
                }
                $index++;
            }
            return 0;
        }
    }
}

#******************************************************************************
# Class for PxPay request messages.
#******************************************************************************
class PxPayRequest extends PxPayMessage
{
    var $UrlFail, $UrlSuccess;
    var $AmountInput;
    var $EnableAddBillCard;
    var $PxPayUserId;
    var $PxPayKey;
    var $Opt;
    #Constructor
    function PxPayRequest()
    {
        $this->PxPayMessage();
        
    }
    function setEnableAddBillCard($EnableBillAddCard)
    {
        $this->EnableAddBillCard = $EnableBillAddCard;
    }
    function setUrlFail($urlFail)
    {
        $this->UrlFail = $urlFail;
    }
    function setUrlSuccess($urlSuccess)
    {
        $this->UrlSuccess = $urlSuccess;
    }
    function setAmountInput($amountInput)
    {
        $this->AmountInput = sprintf("%9.2f", $amountInput);
    }
    function setUserId($userId)
    {
        $this->PxPayUserId = $userId;
    }
    function setKey($key)
    {
        $this->PxPayKey = $key;
    }
    function setOpt($Opt)
    {
        $this->Opt = $Opt;
    }
    #******************************************************************
    #Data validation 
    #******************************************************************
    function validData()
    {
        $msg = "";
        if ($this->TxnType != "Purchase")
            if ($this->TxnType != "Auth")
                $msg = "Invalid TxnType[$this->TxnType]<br>";
        if (strlen($this->MerchantReference) > 64)
            $msg = "Invalid MerchantReference [$this->MerchantReference]<br>";
        if (strlen($this->TxnId) > 16)
            $msg = "Invalid TxnId [$this->TxnId]<br>";
        if (strlen($this->TxnData1) > 255)
            $msg = "Invalid TxnData1 [$this->TxnData1]<br>";
        if (strlen($this->TxnData2) > 255)
            $msg = "Invalid TxnData2 [$this->TxnData2]<br>";
        if (strlen($this->TxnData3) > 255)
            $msg = "Invalid TxnData3 [$this->TxnData3]<br>";
        if (strlen($this->EmailAddress) > 255)
            $msg = "Invalid EmailAddress [$this->EmailAddress]<br>";
        if (strlen($this->UrlFail) > 255)
            $msg = "Invalid UrlFail [$this->UrlFail]<br>";
        if (strlen($this->UrlSuccess) > 255)
            $msg = "Invalid UrlSuccess [$this->UrlSuccess]<br>";
        if (strlen($this->BillingId) > 32)
            $msg = "Invalid BillingId [$this->BillingId]<br>";
        if ($msg != "") {
            trigger_error($msg, E_USER_ERROR);
            return false;
        }
        return true;
    }
    
}

#******************************************************************************
# Abstract base class for PxPay messages.
# These are messages with certain defined elements,  which can be serialized to XML.

#******************************************************************************
class PxPayMessage
{
    var $TxnType;
    var $CurrencyInput;
    var $TxnData1;
    var $TxnData2;
    var $TxnData3;
    var $MerchantReference;
    var $EmailAddress;
    var $BillingId;
    var $TxnId;
    function PxPayMessage()
    {
    }
    function setBillingId($BillingId)
    {
        $this->BillingId = $BillingId;
    }
    function getBillingId()
    {
        return $this->BillingId;
    }
    function setTxnType($TxnType)
    {
        $this->TxnType = $TxnType;
    }
    function getTxnType()
    {
        return $this->TxnType;
    }
    function setCurrencyInput($CurrencyInput)
    {
        $this->CurrencyInput = $CurrencyInput;
    }
    function getCurrencyInput()
    {
        return $this->CurrencyInput;
    }
    function setMerchantReference($MerchantReference)
    {
        $this->MerchantReference = $MerchantReference;
    }
    function getMerchantReference()
    {
        return $this->MerchantReference;
    }
    function setEmailAddress($EmailAddress)
    {
        $this->EmailAddress = $EmailAddress;
    }
    function getEmailAddress()
    {
        return $this->EmailAddress;
    }
    function setTxnData1($TxnData1)
    {
        $this->TxnData1 = $TxnData1;
    }
    function getTxnData1()
    {
        return $this->TxnData1;
    }
    function setTxnData2($TxnData2)
    {
        $this->TxnData2 = $TxnData2;
    }
    function getTxnData2()
    {
        return $this->TxnData2;
    }
    function getTxnData3()
    {
        return $this->TxnData3;
    }
    function setTxnData3($TxnData3)
    {
        $this->TxnData3 = $TxnData3;
    }
    function setTxnId($TxnId)
    {
        $this->TxnId = $TxnId;
    }
    function getTxnId()
    {
        return $this->TxnId;
    }
    function toXml()
    {
        $arr = get_object_vars($this);
        $xml = "<GenerateRequest>";
        while (list($prop, $val) = each($arr))
            $xml .= "<$prop>$val</$prop>";
        $xml .= "</GenerateRequest>";
        return $xml;
    }
}

#******************************************************************************
# Class for PxPay response messages.
#******************************************************************************

class PxPayResponse extends PxPayMessage
{
    var $Success;
    var $AuthCode;
    var $CardName;
    var $CardHolderName;
    var $CardNumber;
    var $DateExpiry;
    var $ClientInfo;
    var $DpsTxnRef;
    var $DpsBillingId;
    var $AmountSettlement;
    var $CurrencySettlement;
    var $TxnMac;
    var $ResponseText;
    var $InputCurrencyName;
    var $Amount;
    function PxPayResponse($xml)
    {
        $msg = new MifMessage($xml);
        $this->PxPayMessage();
        $this->Success = $msg->getElementText("Success");
        $this->setTxnType($msg->getElementText("TxnType"));
        $this->CurrencyInput = $msg->getElementText("CurrencyInput");
        $this->setMerchantReference($msg->getElementText("MerchantReference"));
        $this->setTxnData1($msg->getElementText("TxnData1"));
        $this->setTxnData2($msg->getElementText("TxnData2"));
        $this->setTxnData3($msg->getElementText("TxnData3"));
        $this->AuthCode       = $msg->getElementText("AuthCode");
        $this->CardName       = $msg->getElementText("CardName");
        $this->CardHolderName = $msg->getElementText("CardHolderName");
        $this->CardNumber     = $msg->getElementText("CardNumber");
        $this->DateExpiry     = $msg->getElementText("DateExpiry");
        $this->ClientInfo     = $msg->getElementText("ClientInfo");
        $this->TxnId          = $msg->getElementText("TxnId");
        $this->setEmailAddress($msg->getElementText("EmailAddress"));
        $this->DpsTxnRef          = $msg->getElementText("DpsTxnRef");
        $this->BillingId          = $msg->getElementText("BillingId");
        $this->DpsBillingId       = $msg->getElementText("DpsBillingId");
        $this->AmountSettlement   = $msg->getElementText("AmountSettlement");
        $this->CurrencySettlement = $msg->getElementText("CurrencySettlement");
        $this->TxnMac             = $msg->getElementText("TxnMac");
        $this->ResponseText       = $msg->getElementText("ResponseText");
    }
    function getSuccess()
    {
        return $this->Success;
    }
    function getAuthCode()
    {
        return $this->AuthCode;
    }
    function getCardName()
    {
        return $this->CardName;
    }
    function getCardHolderName()
    {
        return $this->CardHolderName;
    }
    function getCardNumber()
    {
        return $this->CardNumber;
    }
    function getDateExpiry()
    {
        return $this->DateExpiry;
    }
    function getClientInfo()
    {
        return $this->ClientInfo;
    }
    function getDpsTxnRef()
    {
        return $this->DpsTxnRef;
    }
    function getDpsBillingId()
    {
        return $this->DpsBillingId;
    }
    function getAmountSettlement()
    {
        return $this->AmountSettlement;
    }
    function getCurrencySettlement()
    {
        $this->CurrencySettlement;
    }
    function getTxnMac()
    {
        return $this->TxnMac;
    }
    function getResponseText()
    {
        return $this->ResponseText;
    }
    function getCurrencyInput()
    {
        return $this->CurrencyInput;
    }
}