18 define(
'DATACASH_LOG_FILE_PREFIX',
'datacash_transactions_account_');
40 private static $_URLS = Array(
41 'live' =>
'https://mars.transaction.datacash.com/Transaction',
42 'test' =>
'https://testserver.datacash.com/Transaction',
67 private $_test_mode = TRUE;
73 private $_log_file_name;
79 private $_config = NULL;
85 private $_request = NULL;
91 private $_response = NULL;
97 private $_success = FALSE;
104 private $_merchant_url;
111 private $_purchase_desc;
118 private $_purchase_time;
124 private $_cardinfo_dir_path;
136 private $_nonthreed_card_types = Array(
'American Express',
'Diners Club',
'Duet',
'GE Capital',
'JCB',
'Laser');
143 private static $_MANDATE_THREED_CARD_TYPES = Array(
'Maestro',
'Switch');
149 private static $_TEST_CARD_NUMBERS = Array(
150 '1000070000000001' =>
'VISA - SUCCESS (Status: 1)',
151 '100063000000007' =>
'VISA - DECLINED (Status: 7)',
152 '10006500000000' =>
'VISA Delta - REFERRED (Status: 7)',
153 '1000010000000007' =>
'MASTER - SUCCESS (Status: 1)',
154 '1000350000000106' =>
'MASTER - DECLINED (Status: 7)',
155 '1000350000000122' =>
'MASTER - REFERRED (Status: 7)',
156 '1000350000000098' =>
'MASTER - No tids (Status: 53)',
157 '1000350000000460' =>
'MASTER - Timeout (Sleep 600s)',
158 '1000350000000395' =>
'MASTER - Missing start (Status: 28)',
159 '1000130000000003' =>
'Maestro - SUCCESS (Status: 1)',
160 '1000310000000019' =>
'Maestro - DECLINED (Status: 7)',
161 '1000060000000002' =>
'Switch - SUCCESS (Status: 1)',
162 '4936000000000000019' =>
'Switch - DECLINED (Status: 7)',
163 '633499100000000004' =>
'Solo - SUCCESS (Status: 1)',
164 '633499999999999997' =>
'Solo - DECLINED (Status: 7)',
165 '1000681548753263' =>
'Laser - SUCCESS (Status: 1)',
166 '1000681548753461' =>
'Laser - DECLINED (Status: 7)',
167 '3528000000000007' =>
'JCB - SUCCESS (Status: 1)',
168 '3528000000000023' =>
'JCB - DECLINED (Status: 7)',
169 '1000350000000007' =>
'MASTER - AVS/CV2 TEST (Amount: 1010.00 - 1010.14)',
184 function __construct($client, $password, $datacash_api_path, $cardinfo_dir_path, $timeout = 60, $test_mode = TRUE)
186 $this->_client = $client;
187 $this->_password = $password;
188 require_once $datacash_api_path;
189 $this->_cardinfo_dir_path = $cardinfo_dir_path;
190 $this->_timeout = $timeout;
191 $this->_test_mode = $test_mode;
192 $this->_log_file_name = DATACASH_LOG_FILE_PREFIX.$this->_client.($test_mode?
'_test' :
'_live');
194 $this->_createConfigurationDocument();
195 $this->_createRequestDocument();
206 private function _createConfigurationDocument()
208 $url = $this->_test_mode? self::$_URLS[
'test'] : self::$_URLS[
'live'];
210 $config_string = <<<HEREDOC
213 <timeout>{$this->_timeout}</timeout>
219 $config =
new DataCash_Document();
220 $config->readDocumentFromString($config_string);
221 $this->_config = $config;
225 if (!isset($GLOBALS[
'config'])) {
226 $GLOBALS[
'config'] = $config;
238 private function _createRequestDocument()
240 $request_string = <<<HEREDOC
243 <client>{$this->_client}</client>
244 <password>{$this->_password}</password>
249 $request =
new DataCash_Document();
250 $request->readDocumentFromString($request_string);
251 $this->_request = $request;
266 @$this->_request->set(
'Request.Transaction.CardTxn.Card.pan', $card_no);
282 @$this->_request->set(
'Request.Transaction.CardTxn.Card.expirydate',
"$month/$year");
298 @$this->_request->set(
'Request.Transaction.CardTxn.Card.startdate',
"$month/$year");
313 @$this->_request->set(
'Request.Transaction.CardTxn.Card.issuenumber', $issue_no);
328 @$this->_request->set(
'Request.Transaction.CardTxn.Card.Cv2Avs.cv2', $cv2);
344 @$this->_request->set(
'Request.Transaction.CardTxn.Card.Cv2Avs.street_address'.$number, $address);
359 @$this->_request->set(
'Request.Transaction.CardTxn.Card.Cv2Avs.postcode', $postcode);
372 @$this->_request->set(
'Request.Transaction.CardTxn.method',
'auth');
387 @$this->_request->set(
'Request.Transaction.TxnDetails.merchantreference', $this->_getUniqueReferenceNumber($merchant_ref));
403 @$this->_request->set(
'Request.Transaction.TxnDetails.amount', sprintf(
'%01.2f',$amount), array(
'currency' => $currency));
421 $this->_merchant_url = $merchant_url;
423 if (strlen($purchase_desc) > 125) {
424 $purchase_desc = substr($purchase_desc, 0, 125);
426 $this->_purchase_desc = $purchase_desc;
427 $this->_purchase_time = $purchase_time;
428 $this->_nonthreed_card_types = array_merge($this->_nonthreed_card_types, $extra_nonthreed_card_types);
441 @$this->_request->set(
'Request.Transaction.TxnDetails.ThreeDSecure.verify',
'yes');
442 @$this->_request->set(
'Request.Transaction.TxnDetails.ThreeDSecure.merchant_url', $this->_merchant_url);
443 @$this->_request->set(
'Request.Transaction.TxnDetails.ThreeDSecure.purchase_desc', $this->_purchase_desc);
444 @$this->_request->set(
'Request.Transaction.TxnDetails.ThreeDSecure.purchase_datetime', date(
'Ymd H:i:s', $this->_purchase_time));
447 @$this->_request->set(
'Request.Transaction.TxnDetails.ThreeDSecure.Browser.device_category', 0);
448 @$this->_request->set(
'Request.Transaction.TxnDetails.ThreeDSecure.Browser.accept_headers', array_get_index($_SERVER,
'HTTP_ACCEPT',
'*/*'));
449 @$this->_request->set(
'Request.Transaction.TxnDetails.ThreeDSecure.Browser.user_agent', array_get_index($_SERVER,
'HTTP_USER_AGENT',
'Mozilla/5.0'));
464 @$this->_request->set(
'Request.Transaction.CardTxn.Card.Cv2Avs.policy', $policy);
479 public function setAuthorization($reference, $pares = NULL, $method =
'threedsecure_authorization_request')
481 @$this->_request->set(
'Request.Transaction.HistoricTxn.reference', $reference);
482 @$this->_request->set(
'Request.Transaction.HistoricTxn.method', $method);
483 if (!is_null($pares)) {
484 @$this->_request->set(
'Request.Transaction.HistoricTxn.pares_message', $pares);
498 $cardinfo = @
new DataCash_CardInfo(Array(
'datadir' => $this->_cardinfo_dir_path,
'pan' => $this->_request->get(
'Request.Transaction.CardTxn.Card.pan')));
499 $invalid = @$cardinfo->validation($this->_request);
500 if (!is_null($invalid)) {
501 $this->_response = $invalid;
506 $this->_card_type = $cardinfo->scheme();
509 if (!in_array($this->_card_type, $this->_nonthreed_card_types)) {
514 $this->_success = $this->_sendRequest();
516 if ($this->_success) {
517 switch (@$this->_response->get(
'Response.status')) {
534 $card_type = @$this->_response->get(
'Response.CardTxn.card_scheme');
536 if (in_array($card_type, self::$_MANDATE_THREED_CARD_TYPES)) {
537 $this->_success = FALSE;
540 $this->_createRequestDocument();
542 $this->
authorize(@$this->_response->get(
'Response.datacash_reference'));
546 $this->_success = FALSE;
551 return $this->_success;
570 $this->_success = $this->_sendRequest();
571 if ($this->_success) {
572 $this->_success = @$this->_response->get(
'Response.status') == 1? 1 : FALSE;
575 return $this->_success;
586 private function _sendRequest()
589 $this->_logRequest();
591 $agent =
new DataCash_SSLAgent($this->_config);
592 $success = @$agent->send($this->_request);
597 $response = $agent->getResponseDocument();
599 $response =
new DataCash_Document(
"Response");
600 @$response->set(
"Response.status", $agent->errno);
601 @$response->set(
"Response.reason", $agent->err_str);
604 $this->_response = $response;
607 $this->_logResponse();
626 switch ($this->_success) {
628 $response[
'TRANSACTION'] = @$this->_response->get(
'Response.datacash_reference');
629 $response[
'TIME'] = @$this->_response->get(
'Response.time');
631 $response[
'STATUS'] = @$this->_response->get(
'Response.reason');
634 $response[
'ACS_URL'] = @$this->_response->get(
'Response.CardTxn.ThreeDSecure.acs_url');
635 $response[
'PAREQ_MESSAGE'] = @$this->_response->get(
'Response.CardTxn.ThreeDSecure.pareq_message');
636 $response[
'TRANSACTION'] = @$this->_response->get(
'Response.datacash_reference');
653 return @$this->_request->get(
'Request.Transaction.TxnDetails.merchantreference');
666 return self::$_TEST_CARD_NUMBERS;
677 private function _logRequest()
679 $message =
"Request\n";
680 $datacash_ref = @$this->_request->get(
'Request.Transaction.HistoricTxn.reference');
681 if ($datacash_ref === FALSE) {
683 $card_no = @$this->_request->get(
'Request.Transaction.CardTxn.Card.pan');
684 $message .=
'Card number: '.substr($card_no, -4).
"\n";
687 if (!empty($this->_card_type)) {
688 $message .=
'Card type: '.$this->_card_type.
"\n";
692 $message .=
'Transaction type: '.@$this->_request->get(
'Request.Transaction.CardTxn.method').
"\n";
695 $message .=
'Merchant reference: '.$this->getMerchantReference().
"\n";
698 $amount_ele = @$this->_request->get(
'Request.Transaction.TxnDetails.amount', FALSE);
699 if ($amount_ele !== FALSE) {
700 $attr_arr = $amount_ele->getAllAttributes();
702 foreach ($attr_arr as $attr) {
703 if ($attr->getName() ==
'currency') {
704 $currency = $attr->getValue();
708 $message .=
'Amount: '.$amount_ele->getText().
' '.$currency.
"\n";
712 $verify = @$this->_request->get(
'Request.Transaction.TxnDetails.ThreeDSecure.verify');
713 if ($verify === FALSE) {
716 $message .=
'3-D Secure check: '.$verify.
"\n";
719 $message .=
"Historic reference: $datacash_ref\n";
720 $message .=
'Transaction type: '.@$this->_request->get(
'Request.Transaction.HistoricTxn.method').
"\n";
723 $this->_log($message);
734 private function _logResponse()
736 $message =
"Response\n";
737 $datacash_ref = @$this->_response->get(
'Response.datacash_reference');
738 if ($datacash_ref !== FALSE) {
740 $message .=
'Transaction result: '.@$this->_response->get(
'Response.reason').
' (status = '.@$this->_response->get(
'Response.status').
")\n";
743 if (@$this->_request->get(
'Request.Transaction.HistoricTxn.reference') === FALSE) {
744 $message .=
'Merchant reference: '.$this->getMerchantReference().
"\n";
748 $message .=
'Datacash reference: '.$datacash_ref.
"\n";
751 $card_type = @$this->_response->get(
'Response.CardTxn.card_scheme');
752 if ($card_type !== FALSE) {
753 $message .=
"Card type by Datacash: $card_type\n";
757 $cv2avs_ele = @$this->_response->get(
'Response.CardTxn.Cv2Avs.cv2avs_status', FALSE);
758 if ($cv2avs_ele !== FALSE) {
759 $message .=
'AVS/CV2 check: '.$cv2avs_ele->getText().
"\n";
760 $attr_arr = $cv2avs_ele->getAllAttributes();
761 foreach ($attr_arr as $attr) {
762 if ($attr->getName() ==
'reversal') {
763 $message .=
'Reversal: '.($attr->getValue() == 0?
'failed' :
'successful').
"\n";
770 $message .=
'HTTP Error: '.@$this->_response->get(
'Response.reason').
' (status = '.@$this->_response->get(
'Response.status').
")\n";
773 $this->_log($message);
788 private function _log($message, $level = E_USER_NOTICE, $encode=FALSE)
790 log_write($message, $this->_log_file_name, $level, $encode);
803 private function _getUniqueReferenceNumber($ref_no)
805 $ref_length = strlen($ref_no);
808 if (!is_numeric(
'0x'.$ref_no) && (($ref_length > 30) || ($ref_length < 6))) {
809 $ref_no = md5($ref_no);
810 $ref_length = strlen($ref_no);
811 }
else if (($ref_length > 32) || ($ref_length < 6)) {
813 $ref_no = md5($ref_no);
814 $ref_length = strlen($ref_no);
820 if ($ref_length > 30) {
821 $ref_no = base_convert($ref_no, 16, 36);