<?php
/**
* Class for payment system.
* @version 0.2
* @author Shaymardanov Maxim
*/
class XPaySystem {
/**
* Constructor for XPaySystem class
*
* @access public
* @param String $UrlXPay internet address
* @param Integer $portXPay internet port
* @param String $siteReference affiliate / partner
* @param String $uriCertificateFile path to certificate file
* @param Array $httpCustomerInfo http customer info. Is format:
array(
'accept' => 'https://merchantSite.net/3dauth.cgi'
,'user_agent' => '25 character field'
);
* @param Array $customerInfo customer info. Not required. Is format:
array(
'name_prefix' => 'Mr.'
,'first_name' => 'Joe'
,'middle_name' => 'A.'
,'last_name' => 'Bloggs'
,'name_suffix' => 'CEng.'
,'company' => 'A COMPANY'
,'street' => 'A STREET'
,'city' => 'A CITY'
,'state_prov' => 'A STATE'
,'postal_code' => 'TE2 3ST'
,'country' => 'Russia'
,'phone' => '0000 111111'
,'email' => 'hide@address.com'
);
* @param Boolean $liveStatus status of certificate test. Default is 'false' and not required.
* @return XPaySystem
* @throws InvalidArgumentException
* @throws XPayException
*/
public function XPaySystem($urlXPay, $portXPay, $siteReference, $uriCertificateFile, array $httpCustomerInfo, array $customerInfo = null, $testStatus = false) {
/* Validation */
if ($urlXPay == null || $urlXPay == '') {
throw new InvalidArgumentException('Net address to XPay server is empty');
}
if ($portXPay == null || $portXPay == '') {
throw new InvalidArgumentException('Net port to XPay server is empty');
}
if ($siteReference == null || $siteReference == '') {
throw new InvalidArgumentException('Affiliate / Partner ID is empty');
}
if ($uriCertificateFile == null || $uriCertificateFile == '') {
throw new InvalidArgumentException('Certificate File (*.pem file) is empty');
}
if (is_file($uriCertificateFile) == false) {
throw new InvalidArgumentException("URI certificate File: '$uriCertificateFile' is not URI file");
}
/* Initializations */
$lastReqest = null;
$lastResponse = null;
$this->urlXPay = $urlXPay;
$this->portXPay = (int) $portXPay;
$this->siteReference = $siteReference;
$this->certificate = file_get_contents($uriCertificateFile);
$this->setHttpCustomerInfo($httpCustomerInfo);
$this->setCustomerInfo($customerInfo);
if ($testStatus == false) {
$this->liveStatus = 'TRUE';
} else {
$this->liveStatus = 'FALSE';
}
$this->socket = null;
}
/**
* A secureCardQuery request is the process used to determine if a credit card
* is in the 3-D Secure scheme.
*
* @access public
* @param Array $operationInfo operation info:<br/>
* <pre>array(
* 'price' => 4500
* ,'currency'=> 'USD'
* );</pre>
* @param Array $cardInfo card info
array(
'card_type' => 'Visa' //Type card
,'card_number' => '1111222233334444' //Number card
,'security_code' => '123' //Security Code (CVC)
,'expiry_date' => '09/08' //Date of expiry card.
,'start_date' => '12/07' //Date of start card.
,'issue' => '01' //Number of issue card
);
* @param $termUrl
* @param $merchantName
* @param String $orderReference order reference can contain any combination
* of alphanumeric characters. Not required.
* @param String $orderInformation order information can contain any
* combination of alphanumeric characters. Not required.
* @return SimpleXMLElement
* @throws XPayException
* @throws InvalidArgumentException
* @throws Exception (network)
*/
public function secureCardQuery(array $operationInfo, array $cardInfo, $termUrl, $merchantName, $orderReference = null, $orderInformation = null) {
/* Validation */
if ($termUrl == null || $termUrl == '') {
throw new InvalidArgumentException('Term URL is empty');
}
if ($merchantName == null || $merchantName == '') {
throw new InvalidArgumentException('Merchant name is empty');
}
else if (strlen($merchantName) > self::AMOUNT_CHARS_IN_MERCHANT_NAME) {
throw new InvalidArgumentException(
'Merchant name=\'' . $merchantName . '\' is not valid. ' .
'String length \'merchant name\' is ' . strlen($merchantName) . '. ' .
'Maximum number of characters is ' . self::AMOUNT_CHARS_IN_MERCHANT_NAME);
}
//Get socket connetcion
$this->socket = $this->getSocketConnect();
//Create customer info xml
$customerInfoXml = $this->getCustomerInfoXml();
$orderXml = $this->getOrderXml($orderReference, $orderInformation);
$request =
'<RequestBlock Version="' . self::XPAY_VERSION_PROTOCOL . '">' .
'<Request Type="ST3DCARDQUERY">' .
'<Operation>' .
'<Amount>' . $operationInfo['price'] . '</Amount>' . //required
'<Currency>' . $operationInfo['currency'] . '</Currency>' .
'<SiteReference>' . $this->siteReference . '</SiteReference>' . //required
'<TermUrl>' . $termUrl . '</TermUrl>' . //required
'<MerchantName>' . $merchantName . '</MerchantName>' . //required
'</Operation>' .
$customerInfoXml .
'<PaymentMethod>' .
'<CreditCard>' .
'<Type>' . $cardInfo['card_type'] . '</Type>' . //required
'<Number>' . $cardInfo['card_number'] . '</Number>' . //required
'<Issue>' . $cardInfo['issue'] . '</Issue>' .
'<StartDate>' . $cardInfo['start_date'] . '</StartDate>' .
'<ExpiryDate>' . $cardInfo['expiry_date'] . '</ExpiryDate>' . //required
'</CreditCard>' .
'</PaymentMethod>' .
$orderXml .
'</Request>' .
'<Certificate>' . $this->certificate . '</Certificate>' .
'</RequestBlock>';
$this->setLastRequest($request);
$result === socket_write($this->socket, $request);
$XmlResponse = null;
while ($out = socket_read($this->socket, 2048)) {
$XmlResponse .= $out;
}
$this->setLastResponse($XmlResponse);
socket_close($this->socket);
$this->socket = null;
//Dell 1 string
$XmlResponse = substr_replace($XmlResponse, '', 0, 16);
//Process response
$objXml = simplexml_load_string($XmlResponse);
$data = $objXml->Response->OperationResponse;
if ($data->Result == 0) {
//Error
throw new XPayException($data->Message, $data->TransactionReference, 0);
}
//Payment is passed
if ($data->Result == 1 || $data->Result == 2) {
return $data;
}
}
/**
* An authorisation request involves the sending of a credit or debit card
* authorisation to an acquiring bank.
*
* @param Array $operationInfo operation info:<br/>
* <pre>array(
* 'price' => 4500
* ,'currency'=> 'USD'
* );</pre>
* @param Array $cardInfo card info
array(
'card_type' => 'Visa' //Type card
,'card_number' => '1111222233334444' //Number card
,'security_code' => '123' //Security Code (CVC)
,'expiry_date' => '09/08' //Date of expiry card.
,'start_date' => '12/07' //Date of start card.
,'issue' => '01' //Number of issue card
);
* @param String $orderReference order reference can contain any combination
* of alphanumeric characters. Not required.
* @param String $orderInformation order information can contain any
* combination of alphanumeric characters. Not required.
* @return Object(SimpleXMLElement)
public 'TransactionReference' => string '21-5-1490593'
public 'TransactionCompletedTimestamp' => string '2008-08-04 03:33:38'
public 'AuthCode' => string 'AUTH CODE:013840'
public 'TransactionVerifier' => string 'A/erdfhket624n9gvAmrrghdeftreth'
public 'Result' => string '1'
public 'SettleStatus' => string '0' (length=1)
public 'SecurityResponseSecurityCode' => string '2'
public 'SecurityResponsePostCode' => string '1'
public 'SecurityResponseAddress' => string '1'
* @access public
* @throws XPayException
* @throws Exception
*/
public function authorisation(array $operationInfo, array $cardInfo, $orderReference = null, $orderInformation = null) {
//Get socket connetcion
$this->socket = $this->getSocketConnect();
//Create customer info xml
$customerInfoXml = $this->getCustomerInfoXml();
$orderXml = $this->getOrderXml($orderReference, $orderInformation);
$request =
'<RequestBlock Live="' . $this->liveStatus . '" Version="' . self::XPAY_VERSION_PROTOCOL . '">' .
'<Request Type="AUTH">' .
'<Operation>' . //required
'<Amount>' . $operationInfo['price'] . '</Amount>' . //required
'<Currency>' . $operationInfo['currency'] . '</Currency>' .
'<SiteReference>' . $this->siteReference . '</SiteReference>' . //required
'<SettlementDay>' . 1 . '</SettlementDay>' .
'</Operation>' .
$customerInfoXml .
'<PaymentMethod>' . //required
'<CreditCard>' .
'<Type>' . $cardInfo['card_type'] . '</Type>' . //required
'<Number>' . $cardInfo['card_number'] . '</Number>' . //required
'<SecurityCode>' . $cardInfo['security_code'] . '</SecurityCode>' .
'<Issue>' . $cardInfo['issue'] . '</Issue>' .
'<StartDate>' . $cardInfo['start_date'] . '</StartDate>' .
'<ExpiryDate>' . $cardInfo['expiry_date'] . '</ExpiryDate>' . //required
'</CreditCard>' .
'</PaymentMethod>' .
$orderXml .
'</Request>' .
'<Certificate>' . $this->certificate . '</Certificate>' .
'</RequestBlock>';
$this->setLastRequest($request);
$result === socket_write($this->socket, $request);
$XmlResponse = null;
while ($out = socket_read($this->socket, 2048)) {
$XmlResponse .= $out;
}
$this->setLastResponse($XmlResponse);
socket_close($this->socket);
$this->socket = null;
//Dell 1 string
$XmlResponse = substr_replace($XmlResponse, '', 0, 16);
//Process response
$objXml = simplexml_load_string($XmlResponse);
$data = $objXml->Response->OperationResponse;
if ($data->Result == 0) {
//Error
throw new XPayException($data->Message, $data->TransactionReference, 0);
}
if ($data->Result == 2) {
//Payment is not passed
throw new XPayException($data->AuthCode, $data->TransactionReference, 2);
}
//Payment is passed
if ($data->Result == 1) {
return $data;
}
}
/**
* An secure authorisation request involves the sending of a credit or debit card
* secure authorisation to an acquiring bank.
*
* @access public
* @param Array $operationInfo operation info:<br/>
array(
'price' => 4500
,'currency'=> 'USD'
);
* @param Array $cardInfo card info. Is format:
array(
'card_type' => 'Visa' //Type card
,'card_number' => '1111222233334444' //Number card
,'security_code' => '123' //Security Code (CVC)
,'expiry_date' => '09/08' //Date of expiry card.
,'start_date' => '12/07' //Date of start card.
,'issue' => '01' //Number of issue card
);
* @param $secureInfo ThreeDSecure. Is format:
array(
'enrolled' => 'Y'
,'pa_res' => 'ABJASDKA+SDKAJ/SGDSAD'
,'md' => 'LFKH/DSPLFIHPO+SEHFIKEHFEFDES'
);
* @param String $orderReference order reference can contain any combination
* of alphanumeric characters. Not required.
* @param String $orderInformation order information can contain any
* combination of alphanumeric characters. Not required.
* @throws XPayException
* @throws InvalidArgumentException
* @throws Exception (network)
*/
public function secureAuthorisation(array $operationInfo, array $cardInfo, $secureInfo, $parentTransactionReference, $orderReference = null, $orderInformation = null) {
/* Validation */
if ($parentTransactionReference == null || $parentTransactionReference == '') {
throw new InvalidArgumentException('Parent transaction reference is empty');
}
//Get socket connetcion
$this->socket = $this->getSocketConnect();
//Create customer info xml
$customerInfoXml = $this->getCustomerInfoXml();
$secureInfoXml = $this->getSecureInfoXml($secureInfo);
$orderXml = $this->getOrderXml($orderReference, $orderInformation);
$request =
'<RequestBlock Version="' . self::XPAY_VERSION_PROTOCOL . '">' .
'<Request Type="ST3DAUTH">' .
'<Operation>' . //required
'<Amount>' . $operationInfo['price'] . '</Amount>' . //required
'<Currency>' . $operationInfo['currency'] . '</Currency>' .
'<SiteReference>' . $this->siteReference . '</SiteReference>' . //required
'<SettlementDay>' . 1 . '</SettlementDay>' .
'</Operation>' .
$customerInfoXml .
'<PaymentMethod>' .
'<CreditCard>' .
'<Type>' . $cardInfo['card_type'] . '</Type>' . //required
'<Number>' . $cardInfo['card_number'] . '</Number>' . //required
'<SecurityCode>' . $cardInfo['security_code'] . '</SecurityCode>' .
'<Issue>' . $cardInfo['issue'] . '</Issue>' .
'<StartDate>' . $cardInfo['start_date'] . '</StartDate>' .
'<ExpiryDate>' . $cardInfo['expiry_date'] . '</ExpiryDate>' . //required
'<ParentTransactionReference>' . $parentTransactionReference . '</ParentTransactionReference>' .
'</CreditCard>' .
$secureInfoXml .
'</PaymentMethod>' .
$orderXml .
'</Request>' .
'<Certificate>' . $this->certificate . '</Certificate>' .
'</RequestBlock>';
$this->setLastRequest($request);
$result === socket_write($this->socket, $request);
$XmlResponse = null;
while ($out = socket_read($this->socket, 2048)) {
$XmlResponse .= $out;
}
$this->setLastResponse($XmlResponse);
socket_close($this->socket);
$this->socket = null;
//Dell 1 string
$XmlResponse = substr_replace($XmlResponse, '', 0, 16);
//Process response
$objXml = simplexml_load_string($XmlResponse);
$data = $objXml->Response->OperationResponse;
if ($data->Result == 0) {
//Error
throw new XPayException($data->Message, $data->TransactionReference, 0);
}
if ($data->Result == 2) {
//Payment is not passed
throw new XPayException($data->AuthCode, $data->TransactionReference, 2);
}
//Payment is passed
if ($data->Result == 1) {
return $data;
}
}
/**
* An authorisation reversal request involves the cancellation of an
* unsettled credit card transaction.
* Note: After an authorisation reversal has taken place the transaction
* cannot be settled.
* @param String $parentTransactionReference the unique SecureTrading
* transaction reference for that transaction.
* @param String $transactionVerifier
* @param String $orderReference order reference can contain any combination
* of alphanumeric characters. Not required.
* @param String $orderInformation order information can contain any
* combination of alphanumeric characters. Not required.
* @return Object(SimpleXMLElement)
public 'TransactionReference' => string '23-5-1451082'
public 'TransactionCompletedTimestamp' => string '2008-08-04 04:50:11'
public 'AuthCode' => string 'REVERSAL OK'
public 'Result' => string '1'
* @access public
* @throws XPayException
* @throws Exception
*/
public function authorisationReversal($parentTransactionReference, $transactionVerifier, $orderReference = null, $orderInformation = null) {
//Get socket connetcion
$this->socket = $this->getSocketConnect();
//Create customer info xml
$customerInfoXml = $this->getCustomerInfoXml();
$orderXml = $this->getOrderXml($orderReference, $orderInformation);
$request =
'<RequestBlock Live="' . $this->liveStatus . '" Version="' . self::XPAY_VERSION_PROTOCOL . '">' .
'<Request Type="AUTHREVERSAL">' .
'<Operation>' . //required
"<SiteReference>$this->siteReference</SiteReference>" . //required
'</Operation>' .
$customerInfoXml .
'<PaymentMethod>' . //required
'<CreditCard>' .
'<TransactionVerifier>' . $transactionVerifier . '</TransactionVerifier>' .
'<ParentTransactionReference>' . $parentTransactionReference . '</ParentTransactionReference>' .
'</CreditCard>' .
'</PaymentMethod>' .
$orderXml .
'</Request>' .
"<Certificate>$this->certificate</Certificate>" .
'</RequestBlock>';
$this->setLastRequest($request);
$result === socket_write($this->socket, $request);
$XmlResponse = null;
while ($out = socket_read($this->socket, 2048)) {
$XmlResponse .= $out;
}
$this->setLastResponse($XmlResponse);
socket_close($this->socket);
$this->socket = null;
//Dell 1 string
$XmlResponse = substr_replace($XmlResponse, '', 0, 16);
//Process response
$objXml = simplexml_load_string($XmlResponse);
$data = $objXml->Response->OperationResponse;
if ($data->Result == 0) {
//Error
throw new XPayException($data->Message, $data->TransactionReference, 0);
}
//Payment is passed
if ($data->Result == 1) {
return $data;
}
}
/**
*
* (Public, Method no tested) A refund request involves the crediting of a credit card after the
* settlement of a successful
* @param Integer $amount - money is formats: 9,45$ = 945 cent = (9 $, 45 cent)
* @param String $parentTransactionReference
* @param String $transactionVerifier
* @throws InvalidArgumentException
* @throws Exception
*/
private function refund($amount, $parentTransactionReference, $transactionVerifier) {
//Validation amount
//$amount = DataValidation::validAmount($amount);
//Get socket connetcion
$this->socket = $this->getSocketConnect();
//Create customer info xml
$customerInfoXml = $this->getCustomerInfoXml();
$request =
'<RequestBlock Live="' . $this->liveStatus . '" Version="3.51">' .
'<Request Type="REFUND">' .
'<Operation>' .
'<Amount>' . $amount . '</Amount>' . //required
"<SiteReference>$this->siteReference</SiteReference>" . //required
'</Operation>' .
$customerInfoXml .
'<PaymentMethod>' .
'<CreditCard>' .
'<ParentTransactionReference>' . $parentTransactionReference . '</ParentTransactionReference>' .
'<TransactionVerifier>' . $transactionVerifier . '</TransactionVerifier>' .
'</CreditCard>' .
'</PaymentMethod>' .
'</Request>' .
"<Certificate>$this->certificate</Certificate>" .
'</RequestBlock>';
$result === socket_write($this->socket, $request);
$response = null;
while ($out = socket_read($this->socket, 2048)) {
$response .= $out;
}
socket_close($this->socket);
$this->socket = null;
return $response;
//$objectXml = simplexml_load_string($response);
}
/**
* (Public, Method no tested) A refund reversal involves reversing a refund on an unsettled refund request.
* @param String $parentTransactionReference the unique SecureTrading
* transaction reference for that transaction.
* @param String $transactionVerifier
* @param String $orderReference order reference can contain any combination
* of alphanumeric characters. Not required.
* @param String $orderInformation order information can contain any
* combination of alphanumeric characters. Not required.
* @throws InvalidArgumentException
* @throws Exception
*/
private function refundReversal($parentTransactionReference, $transactionVerifier, $orderReference = null, $orderInformation = null) {
//Get socket connetcion
$this->socket = $this->getSocketConnect();
//Create customer info xml
$customerInfoXml = $this->getCustomerInfoXml();
$orderXml = $this->getOrderXml($orderReference, $orderInformation);
$request =
'<RequestBlock Live="' . $this->liveStatus . '" Version="3.51">' .
'<Request Type="REFUNDREVERSAL">' .
'<Operation>' . //required
"<SiteReference>$this->siteReference</SiteReference>" . //required
'</Operation>' .
$customerInfoXml .
'<PaymentMethod>' . //required
'<CreditCard>' .
'<ParentTransactionReference>' . $parentTransactionReference . '</ParentTransactionReference>' .
'<TransactionVerifier>' . $transactionVerifier . '</TransactionVerifier>' .
'</CreditCard>' .
'</PaymentMethod>' .
$orderXml .
'</Request>' .
"<Certificate>$this->certificate</Certificate>" .
'</RequestBlock>';
echo $request;
$result === socket_write($this->socket, $request);
$response = null;
while ($out = socket_read($this->socket, 2048)) {
$response .= $out;
}
socket_close($this->socket);
$this->socket = null;
return $response;
}
/**
* (Public, Method no tested) Settlement involves the transfer of authorised funds to the merchants
* bank account.
* @param Integer $settleAmount
* @param String $settleDate is format: "YYYY-MM-DD"
* @param String $transactionReference
* @param Integer $settleStatus is default = 0.
* 0: The transaction is pending settlement and will be included in the
* fraud checking system (This is the default value for all transactions)
* 1: The transaction is pending settlement and wont be included in the
* fraud checking system
* 2: The transaction is suspended
* @return void
* @throws InvalidArgumentException
* @throws Exception
*/
private function settlement($settleAmount, $settleDate, $transactionReference, $settleStatus = 0) {
//Validation amount
//$settleAmount = DataValidation::validAmount($settleAmount);
//Validation settleDate
//$settleDate = DataValidation::validSettleDate($settleDate);
//Validation $settleStatus
if ($settleStatus < 0 || $settleStatus > 2) {
throw new InvalidArgumentException(
'Type settle status=\'' . $settleStatus . '\' is not valid. ' .
'Valid is 0, 1, 2.' . "\n" .
'0: The transaction is pending settlement and will ' . "\n" .
'be included in the fraud checking system (This is the default value for all transactions).' .
'1: The transaction is pending settlement and wont be included in the ' . "\n" .
'fraud checking system.' .
'2: The transaction is suspended.');
}
//Get socket connetcion
$this->socket = $this->getSocketConnect();
//Create customer info xml
$customerInfoXml = $this->getCustomerInfoXml();
$request =
'<RequestBlock Live="' . $this->liveStatus . '" Version="3.51">' .
'<Request Type="SETTLEMENT">' .
'<Operation>' .
"<SiteReference>$this->siteReference</SiteReference>" . //required
'<TransactionReference>' . $transactionReference . '</TransactionReference>' .
'<SettleDate>' . $settleDate . '</SettleDate>' .
'<SettleStatus>' . $settleStatus . '</SettleStatus>' .
'<SettleAmount>' . $settleAmount . '</SettleAmount>' .
'</Operation>' .
'</Request>' .
"<Certificate>$this->certificate</Certificate>" .
'</RequestBlock>';
$result === socket_write($this->socket, $request);
$response = null;
while ($out = socket_read($this->socket, 2048)) {
$response .= $out;
}
socket_close($this->socket);
$this->socket = null;
return $response;
//$objectXml = simplexml_load_string($response);
}
/**
* Get last request
* @return String last request
*/
public function getLastRequest() {
return $this->lastReqest;
}
/**
* Set last request
*/
private function setLastRequest($lastRequest) {
$this->lastReqest = $lastRequest;
}
/**
* Get last response
* @return String last response
*/
public function getLastResponse() {
return $this->lastResponse;
}
/**
* Set last response
*/
private function setLastResponse($lastResponse) {
$this->lastResponse = $lastResponse;
}
/**
* Convert object to string
* @return String status object
*/
public function __toString() {
return __FILE__ . ':' . __CLASS__ .
'[Fundamental:' .
'$urlXPay=' . $this->urlXPay .
',$portXPay=' . $this->portXPay .
',$siteReference=' . $this->siteReference .
',$socket=' . $this->socket .
']' .
'[CustomerNameInfo:' .
'$prefixName=' . $this->customerInfo['name_prefix'] .
',$firstName=' . $this->customerInfo['first_name'] .
',$middleName=' . $this->customerInfo['middle_name'] .
',$lastName=' . $this->customerInfo['last_name'] .
',$suffixName=' . $this->customerInfo['name_suffix'] .
']' .
'[CustomerInfo:' .
'$company=' . $this->customerInfo['company'] .
',$street=' . $this->customerInfo['street'] .
',$city=' . $this->customerInfo['city'] .
',$stateProv=' . $this->customerInfo['state_prov'] .
',$postalCode=' . $this->customerInfo['postal_code'] .
',$countryCode=' . $this->customerInfo['country_code'] .
',$phone=' . $this->customerInfo['phone'] .
',$email=' . $this->customerInfo['email'] .
']';
}
/**
* Устанавливает соендинение с Xpay сервером и возвращяет это сендинение в
* виде socket_connect.
*
* @throws Exception
* @return resource socket connect
*/
private function getSocketConnect() {
//Create socket
if (false == ($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
throw new Exception(
'socket_create() failed. Reason: ' . socket_strerror(socket_last_error()));
}
//Create socket connection
if (false == ($result = socket_connect($socket, $this->urlXPay, $this->portXPay))) {
throw new Exception(
"socket_connect() failed. Reason: ($result) " . socket_strerror(socket_last_error($this->socket)) .
'Most likely not running XPay server.');
}
return $socket;
}
/**
* Set customer info
* @param Array $customerInfo is format:
array(
'name_prefix' => 'Mr.'
,'first_name' => 'Joe'
,'middle_name' => 'A.'
,'last_name' => 'Bloggs'
,'name_suffix' => 'CEng.'
,'company' => 'A COMPANY'
,'street' => 'A STREET'
,'city' => 'A CITY'
,'state_prov' => 'A STATE'
,'postal_code' => 'TE2 3ST'
,'country' => 'Russia'
,'phone' => '0000 111111'
,'email' => 'hide@address.com'
);
* @return void
*/
private function setCustomerInfo($customerInfo) {
if ($customerInfo == null) {
$this->customerInfo = null;
} else {
if ($customerInfo['country'] != null) {
$customerInfo['country_code'] = Convert::nameToCountryCode($customerInfo['country']);
}
$this->customerInfo = $customerInfo;
}
}
/**
* Set customer info
* @param Array $httpCustomerInfo is format:
array(
'accept' => 'https://merchantSite.net/3dauth.cgi'
,'user_agent' => '25 character field'
);
* @return void
* @throws InvalidArgumentException
*/
private function setHttpCustomerInfo(array $httpCustomerInfo) {
if ($httpCustomerInfo == null) {
throw new InvalidArgumentException(
'Http customer info (Accept and UserAgent) is empty');
}
else {
$this->httpCustomerInfo = $httpCustomerInfo;
}
}
/**
* Get customer info in XML format
* @return String "<CustomerInfo> ... </CustomerInfo>"
*/
private function getCustomerInfoXml() {
if ($this->customerInfo == null) {
$customerInfoXml =
'<CustomerInfo>' .
'<Accept>' . $this->httpCustomerInfo['accept'] . '</Accept>' .
'<UserAgent>' . $this->httpCustomerInfo['user_agent'] . '</UserAgent>' .
'</CustomerInfo>';
}
else {
$customerInfoXml =
'<CustomerInfo>' .
'<Postal>' .
'<Name>' .
'<NamePrefix>' . $this->customerInfo['name_prefix'] . '</NamePrefix>' .
'<FirstName>' . $this->customerInfo['first_name'] . '</FirstName>' .
'<MiddleName>' . $this->customerInfo['middle_name'] . '</MiddleName>' .
'<LastName>' . $this->customerInfo['last_name'] . '</LastName>' .
'<NameSuffix>' . $this->customerInfo['name_suffix'] . '</NameSuffix>' .
'</Name>' .
'<Company>' . $this->customerInfo['company'] . '</Company>' .
'<Street>' . $this->customerInfo['street'] . '</Street>' .
'<City>' . $this->customerInfo['city'] . '</City>' .
'<StateProv>' . $this->customerInfo['state_prov'] . '</StateProv>' .
'<PostalCode>' . $this->customerInfo['postal_code'] . '</PostalCode>' .
'<CountryCode>' . $this->customerInfo['country_code'] . '</CountryCode>' .
'</Postal>' .
'<Telecom>' .
'<Phone>' . $this->customerInfo['phone'] . '</Phone>' .
'</Telecom>' .
'<Online>' .
'<Email>' . $this->customerInfo['email'] . '</Email>' .
'</Online>' .
'<Accept>' . $this->httpCustomerInfo['accept'] . '</Accept>' .
'<UserAgent>' . $this->httpCustomerInfo['user_agent'] . '</UserAgent>' .
'</CustomerInfo>';
return $customerInfoXml;
}
}
/**
* Get secure info xml
*
* @param $secureInfo is format:
array(
'enrolled' => 'Y'
,'pa_res' => 'ABJASDKA+SDKAJ/SGDSAD'
,'md' => 'LFKH/DSPLFIHPO+SEHFIKEHFEFDES'
);
*/
private function getSecureInfoXml($secureInfo) {
/* Validation */
if ($secureInfo['enrolled'] == null || $secureInfo['enrolled'] == '') {
throw new InvalidArgumentException('Secure Info: Enrolled is empty');
}
/*
if ($secureInfo['pa_res'] == null || $secureInfo['pa_res'] == '') {
throw new InvalidArgumentException('Secure Info: PaRes is empty');
}
if ($secureInfo['md'] == null || $secureInfo['md'] == '') {
throw new InvalidArgumentException('Secure Info: MD is empty');
}
*/
$secureInfoXml = null;
if ($secureInfo['enrolled'] == 'Y') {
$secureInfoXml =
'<ThreeDSecure>' .
'<Enrolled>' . $secureInfo['enrolled'] . '</Enrolled>' .
'<PaRes>' . $secureInfo['pa_res'] . '</PaRes>' .
'<MD>' . $secureInfo['md'] . '</MD>' .
'</ThreeDSecure>';
}
else {
$secureInfoXml =
'<ThreeDSecure>' .
'<Enrolled>' . $secureInfo['enrolled'] . '</Enrolled>' .
'<PaRes></PaRes>' .
'<MD>' . $secureInfo['md'] . '</MD>' .
'</ThreeDSecure>';
}
return $secureInfoXml;
}
/**
* Get order in XML format
* It should be noted that the maximum number of characters a tag can store is 255.
* @param String $reference order reference can contain any combination of
* alphanumeric characters
* @param String $information order information can contain any combination of
* alphanumeric characters
* @return String "<Order> ... </Order>"
* @throws InvalidArgumentException
*/
private function getOrderXml($reference, $information = null) {
if ($reference == null && $information == null) {
return null;
}
if (strlen($reference) > self::MAX_AMOUNT_CHARS_TEGS_OF_ORDER) {
throw new InvalidArgumentException(
'Order reference=\'' . $reference . '\' is not valid. ' .
'String length \'order reference\' is ' . strlen($reference) . '. ' .
'Maximum number of characters is ' . self::MAX_AMOUNT_CHARS_TEGS_OF_ORDER);
}
$order = '<Order>' .
'<OrderReference>' . $reference . '</OrderReference>';
if ($information != null) {
if (strlen($information) > self::MAX_AMOUNT_CHARS_TEGS_OF_ORDER) {
throw new InvalidArgumentException(
'Order reference=\'' . $information . '\' is not valid. ' .
'String length \'order reference\' is ' . strlen($information) . '. ' .
'Maximum number of characters is ' . self::MAX_AMOUNT_CHARS_TEGS_OF_ORDER);
}
$order .= '<OrderInformation>' . $information . '</OrderInformation>';
}
$order .= '</Order>';
}
/**
* For testing class
*/
private $liveStatus;
/**
* Net address to XPay server
*/
private $urlXPay;
/**
* Net port to XPay server
*/
private $portXPay;
/**
* Affiliate / Partner ID
*/
private $siteReference;
/**
* Certificate
*/
private $certificate;
/**
* Socket for work with server
*/
private $socket;
/**
* Customer info is format:
array(
'name_prefix' => 'Mr.'
'first_name' => 'Joe'
'middle_name' => 'A.'
'last_name' => 'Bloggs'
'name_suffix' => 'CEng.'
'company' => 'A COMPANY'
'city' => 'A CITY'
'state_prov' => 'A STATE'
'postal_code' => 'TE2 3ST'
'country_code' => 'RU'
'phone' => '0000 111111'
'email' => 'hide@address.com'
);
* @var Array
*/
private $customerInfo;
/**
* Array customer info is format:
array(
'accept' => 'https://merchantSite.net/3dauth.cgi'
,'user_agent' => '25 character field'
);
* @var Array
*/
private $httpCustomerInfo;
/**
* Last reqest
* @var string
*/
private $lastReqest;
/**
* Last response
* @var string
*/
private $lastResponse;
/**
* Amount chars in nomer card
*/
const AMOUNT_CHARS_IN_NOMER_CARD = 16;
/**
* Amount chars in expiry date
*/
const AMOUNT_CHARS_IN_EXPIRY_DATE = 5;
/**
* Amount chars in settle date
*/
const AMOUNT_CHARS_IN_SETTLE_DATE = 10;
/**
* Amount chars in merchant name
*/
const AMOUNT_CHARS_IN_MERCHANT_NAME = 25;
/**
* Maximum amount chars in tegs of order
*/
const MAX_AMOUNT_CHARS_TEGS_OF_ORDER = 255;
/**
* XPay version protcol
*/
const XPAY_VERSION_PROTOCOL = 3.51;
}
/**
* XPay Exception
*/
class XPayException extends RuntimeException {
public function XPayException($message, $transactionId, $code) {
parent::__construct($message, $code);
$this->transactionId = $transactionId;
}
/**
* Get Transaction reference
* @return Transaction reference, is format: '64-2-736166'
*/
public function getTransactionId() {
return $this->transactionId;
}
/**
* Transaction reference
*/
private $transactionId;
}
?>