18 define(
'SAGEPAY_LOG_FILE_PREFIX',
'sagepay_transactions_account_');
40 private static $_URLS = Array(
42 'payment_registration' =>
'https://live.sagepay.com/gateway/service/vspdirect-register.vsp',
43 'threeds_callback' =>
'https://live.sagepay.com/gateway/service/direct3dcallback.vsp',
46 'payment_registration' =>
'https://test.sagepay.com/gateway/service/vspdirect-register.vsp',
47 'threeds_callback' =>
'https://test.sagepay.com/gateway/service/direct3dcallback.vsp',
50 'payment_registration' =>
'https://test.sagepay.com/simulator/VSPDirectGateway.asp',
51 'threeds_callback' =>
'https://test.sagepay.com/simulator/VSPDirectCallback.asp',
59 private $_post_string;
72 private $_merchant_ref;
78 private $_card_number;
108 private $_gift_aid =
'no';
120 private $_log_file_name;
126 private $_response = NULL;
132 private $_success = FALSE;
138 private static $_TEST_CARD_NUMBERS = Array(
139 '4929000000006' =>
'Visa',
140 '4462000000000003' =>
'Visa Delta',
141 '4917300000000008' =>
'Visa Electron',
142 '5404000000000001' =>
'MasterCard',
143 '300000000000000004' =>
'Maestro',
144 '5641820000000005' =>
'Switch (UK Maestro)',
145 '6334900000000005' =>
'Solo',
146 '374200000000004' =>
'American Express',
147 '36000000000008' =>
'Diners Club',
148 '3569990000000009' =>
'JCB',
149 '6304990000000000044' =>
'Laser',
156 private static $_CARD_TYPES = Array(
158 'DELTA' =>
'Visa Delta',
159 'UKE' =>
'Visa Electron',
160 'MC' =>
'MasterCard',
161 'MAESTRO' =>
'Maestro',
163 'AMEX' =>
'American Express',
164 'DC' =>
'Diners Club',
179 function __construct($protocol, $vendor, $timeout = 60, $run_mode =
'Simulator')
181 $this->_post_string =
"VPSProtocol=$protocol&Vendor=$vendor";
182 $this->_timeout = $timeout;
183 $this->_post_urls = self::$_URLS[$run_mode];
184 $this->_log_file_name = SAGEPAY_LOG_FILE_PREFIX.$vendor.
'_'.strtolower($run_mode);
199 $this->_post_string .=
'&CardHolder='.urlencode($card_name);
215 $this->_card_number = substr($card_no, -4);
216 $this->_post_string .=
"&CardNumber=$card_no";
232 $this->_post_string .=
"&ExpiryDate=$month$year";
248 $this->_post_string .=
"&StartDate=$month$year";
263 $this->_post_string .=
"&IssueNumber=$issue_no";
278 $this->_post_string .=
"&CV2=$cv2";
291 $this->_tx_type =
'PAYMENT';
292 $this->_post_string .=
"&TxType=PAYMENT";
307 $this->_merchant_ref = $this->_getUniqueReferenceNumber($merchant_ref);
308 $this->_post_string .=
'&VendorTxCode='.$this->_merchant_ref;
324 $this->_amount = sprintf(
'%01.2f',$amount);
325 $this->_currency = $currency;
326 $this->_post_string .=
'&Amount='.$this->_amount.
"&Currency=$currency";
341 $this->_post_string .=
'&Description='.urlencode($desc);
356 $this->_card_type = $card_type;
357 $this->_post_string .=
"&CardType=$card_type";
372 $this->_post_string .=
'&BillingFirstnames='.urlencode($first_names);
387 $this->_post_string .=
'&BillingSurname='.urlencode($surname);
402 $this->_post_string .=
'&BillingAddress1='.urlencode($address);
417 $this->_post_string .=
'&BillingAddress2='.urlencode($address);
432 $this->_post_string .=
'&BillingCity='.urlencode($city);
447 $this->_post_string .=
'&BillingPostCode='.urlencode($postcode);
462 $this->_post_string .=
'&BillingCountry='.urlencode($country);
477 $this->_post_string .=
'&BillingState='.urlencode($state);
492 $this->_post_string .=
'&BillingPhone='.urlencode($phone_no);
507 $this->_post_string .=
'&DeliveryFirstnames='.urlencode($first_names);
522 $this->_post_string .=
'&DeliverySurname='.urlencode($surname);
537 $this->_post_string .=
'&DeliveryAddress1='.urlencode($address);
552 $this->_post_string .=
'&DeliveryAddress2='.urlencode($address);
567 $this->_post_string .=
'&DeliveryCity='.urlencode($city);
582 $this->_post_string .=
'&DeliveryPostCode='.urlencode($postcode);
597 $this->_post_string .=
'&DeliveryCountry='.urlencode($country);
612 $this->_post_string .=
'&DeliveryState='.urlencode($state);
627 $this->_post_string .=
'&DeliveryPhone='.urlencode($phone_no);
640 $this->_post_string .=
'&Apply3DSecure=0';
653 $this->_post_string .=
'&ApplyAVSCV2=0';
666 $this->_gift_aid =
'yes';
667 $this->_post_string .=
'&GiftAidPayment=1';
681 $this->_success = $this->_sendRequest($this->_post_urls[
'payment_registration']);
683 if ($this->_success) {
684 switch ($this->_response[
'Status']) {
692 $this->_success = FALSE;
696 return $this->_success;
714 $this->_merchant_ref = $merchant_ref;
715 $this->_tx_type =
'3-D Secure Authorization Callback';
718 $this->_post_string =
"MD=$md&PARes=".urlencode($pares);
721 $this->_success = $this->_sendRequest($this->_post_urls[
'threeds_callback']);
723 if ($this->_success) {
724 $this->_success = $this->_response[
'Status'] ==
'OK'? 1 : FALSE;
727 return $this->_success;
740 private function _sendRequest($url)
745 $this->_logRequest();
749 'POSTFIELDS' => $this->_post_string,
750 'RETURNTRANSFER' => 1,
751 'TIMEOUT' => $this->_timeout,
752 'SSL_VERIFYPEER' => 1,
753 'SSL_VERIFYHOST' => 2,
755 $details = fetch_url($url, $options);
756 $response = $details[
'response'];
758 if ($response === FALSE) {
760 $response = Array(
'CURL_ERROR' => TRUE,
'Status' =>
'CURL_ERROR_'.$details[
'errornumber'],
'StatusDetail' => $details[
'errorstring']);
762 $lines = explode(
"\r\n", $response);
764 foreach ($lines as $line) {
766 $key_val_pairs = explode(
'=', $line, 2);
767 $response[$key_val_pairs[0]] = $key_val_pairs[1];
772 $this->_response = $response;
775 $this->_logResponse();
794 switch ($this->_success) {
796 $response[
'TRANSACTION'] = $this->_response[
'VPSTxId'];
797 $response[
'TIME'] = time();
799 $response[
'STATUS'] = $this->_response[
'StatusDetail'];
802 $response[
'ACS_URL'] = $this->_response[
'ACSURL'];
803 $response[
'PAREQ_MESSAGE'] = $this->_response[
'PAReq'];
804 $response[
'MD'] = $this->_response[
'MD'];
821 return $this->_merchant_ref;
834 return self::$_TEST_CARD_NUMBERS;
847 return self::$_CARD_TYPES;
858 private function _logRequest()
860 $message =
"Request\n";
861 if (empty($this->_card_number)) {
862 $message .=
"Historic reference: {$this->getMerchantReference()}\n";
866 $message .=
"Card number: {$this->_card_number}\n";
869 $message .=
"Card type: {$this->_card_type}\n";
872 $message .=
"Merchant reference: {$this->getMerchantReference()}\n";
875 $message .=
"Amount: {$this->_amount} {$this->_currency}\n";
878 $message .=
"Gift Aid Payment: {$this->_gift_aid}\n";
883 $message .=
"Transaction type: {$this->_tx_type}\n";
885 $this->_log($message);
896 private function _logResponse()
898 $message =
"Response\n";
899 if (array_get_index($this->_response,
'CURL_ERROR', FALSE)) {
900 $message .=
'CURL Error: '.$this->_response[
'StatusDetail'].
' (status = '.$this->_response[
'Status'].
")\n";
904 $message .=
'Transaction result: '.$this->_response[
'Status'].
"\n";
907 if (isset($this->_response[
'StatusDetail'])) {
908 $message .=
'Status details: '.$this->_response[
'StatusDetail'].
"\n";
912 $message .=
"Merchant reference: {$this->getMerchantReference()}\n";
915 if (isset($this->_response[
'VPSTxId'])) {
916 $message .=
'Transaction ID: '.$this->_response[
'VPSTxId'].
"\n";
920 if (isset($this->_response[
'SecurityKey'])) {
921 $message .=
'Security Key: '.$this->_response[
'SecurityKey'].
"\n";
925 if (isset($this->_response[
'TxAuthNo'])) {
926 $message .=
'Authorization code: '.$this->_response[
'TxAuthNo'].
"\n";
930 if (isset($this->_response[
'3DSecureStatus'])) {
931 $message .=
'3-D Secure Status: '.$this->_response[
'3DSecureStatus'].
"\n";
935 if (isset($this->_response[
'CAVV'])) {
936 $message .=
'3-D Secure Result Code: '.$this->_response[
'CAVV'].
"\n";
941 $this->_log($message);
956 private function _log($message, $level = E_USER_NOTICE, $encode=FALSE)
958 log_write($message, $this->_log_file_name, $level, $encode);
971 private function _getUniqueReferenceNumber($ref_no)
973 if (strlen($ref_no) > 40) {
974 $ref_no = md5($ref_no);