18 require_once dirname(__FILE__).
'/../../payment_gateway/payment_gateway.inc';
19 require_once dirname(__FILE__).
'/datacash_processor.inc';
41 private $_redirect_info = NULL;
47 private $_pass_through_vars = NULL;
58 parent::__construct($assetid);
75 if (!parent::_createAdditional($link))
return FALSE;
77 return ($this->
_createBodycopy(
'display_format', translate(
'default_bodycopy_content')) && $this->
_createBodycopy(
'card_holder_verification', translate(
'card_holder_verification_bodycopy_content')));
93 $GLOBALS[
'SQ_SYSTEM']->am->includeAsset(
'bodycopy');
95 $copy_link = Array(
'asset' => &$this,
'link_type' => SQ_LINK_TYPE_2,
'is_dependant' => 1,
'is_exclusive' => 1,
'value' => $link_value);
97 $bodycopy->setAttrValue(
'name', ucwords(str_replace(
'_',
' ', $link_value)));
98 $args = Array(
'content' => $content);
99 if ($bodycopy->create($copy_link, $args)) {
100 $child_bodycopy = $GLOBALS[
'SQ_SYSTEM']->am->getLink($bodycopy->id, SQ_LINK_TYPE_2,
'bodycopy_div');
101 $GLOBALS[
'SQ_SYSTEM']->am->releaseLock($child_bodycopy[
'minorid'],
'attributes');
118 $page_links = parent::_getAllowedLinks();
119 $page_links[SQ_LINK_TYPE_2][
'bodycopy'] = Array(
'card' => 2,
'exclusive' => TRUE);
140 $keywords = parent::getAvailableKeywords();
142 $keywords[
'card_number'] =
'Card Number';
143 $keywords[
'card_start_month'] =
'Card Start Month';
144 $keywords[
'card_start_year'] =
'Card Start Year';
145 $keywords[
'card_expiry_month'] =
'Card Expiry Month';
146 $keywords[
'card_expiry_year'] =
'Card Expiry Year';
147 $keywords[
'card_issue_number'] =
'Card Issue Number';
148 $keywords[
'card_cv2'] =
'Card CV2';
150 $keywords[
'street_address1'] =
'Street Address 1';
151 $keywords[
'street_address2'] =
'Street Address 2';
152 $keywords[
'street_address3'] =
'Street Address 3';
153 $keywords[
'street_address4'] =
'Street Address 4';
154 $keywords[
'postcode'] =
'Postcode';
156 $keywords[
'transaction_amount'] =
'Transaction Amount';
157 $keywords[
'transaction_currency'] =
'Transaction Currency';
158 $keywords[
'processing_error'] =
'Processing Error (empty if no error)';
159 $keywords[
'submit_button'] =
'Submit Button';
160 $keywords[
'cancel_button'] =
'Cancel Button';
161 $keywords[
'reset_button'] =
'Reset Button';
162 $keywords[
'card_holder_verification_form'] =
'Card Holder Verification Form';
182 $vars[
'keywords'] = array_merge($vars[
'keywords'], $keywords);
196 if (array_get_index($_GET,
'unknown_referer', FALSE)) {
197 trigger_error(
'Unknown caller reference');
202 if (array_get_index($_GET,
'error_message', FALSE)) {
203 $this->_setError($_GET[
'error_message']);
207 $is_in_frame = FALSE;
209 if (empty($_POST[
'PaRes']) || empty($_POST[
'MD'])) {
211 $amount = array_get_index($_SESSION,
'SQ_ECOM_AMOUNT', 0);
212 $card_info = array_get_index($_REQUEST, $this->
getPrefix().
'_card', FALSE);
213 $action = array_get_index($_REQUEST, $this->
getPrefix().
'_action', FALSE);
215 if ($action ==
'Cancel') {
218 }
else if (empty($amount)) {
219 unset($_SESSION[
'SQ_ECOM_AMOUNT']);
220 $this->_unsetCurrency();
222 if (isset($_SESSION[
'SQ_ECOM_PASS_THROUGH_VARS'])) {
223 unset($_SESSION[
'SQ_ECOM_PASS_THROUGH_VARS']);
230 }
else if ($card_info) {
235 if ($success === 2) {
237 $_SESSION[
'SQ_ECOM_TRANSACTION_REF_NO'] = $this->_redirect_info[
'TRANSACTION'];
244 }
else if (!empty($_SESSION[
'SQ_ECOM_TRANSACTION_REF_NO']) && ($_POST[
'MD'] == md5($_SESSION[
'SQ_ECOM_REF_NO']))) {
247 $datacash_ref = $_SESSION[
'SQ_ECOM_TRANSACTION_REF_NO'];
248 unset($_SESSION[
'SQ_ECOM_TRANSACTION_REF_NO']);
250 if ($success === FALSE) {
252 $this->_redirectParent($this->
getURL().
'?error_message='.urlencode($this->_tmp[
'error_message'][0]));
257 if ($success === 1) {
258 unset($_SESSION[
'SQ_ECOM_AMOUNT']);
259 $this->_unsetCurrency();
261 if (isset($_SESSION[
'SQ_ECOM_PASS_THROUGH_VARS'])) {
262 unset($_SESSION[
'SQ_ECOM_PASS_THROUGH_VARS']);
265 if (isset($_SESSION[
'SQ_ECOM_PAYMENT_COMPLETED_BROADCASTER_ASSETID'])) {
266 $broadcaster = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($_SESSION[
'SQ_ECOM_PAYMENT_COMPLETED_BROADCASTER_ASSETID']);
267 if (!empty($broadcaster)) {
269 $response = array_get_index($_SESSION,
'SQ_ECOM_RESPONSE', FALSE);
271 $_POST[
'transaction_reference'] = $response[
'TRANSACTION'];
272 $_POST[
'transaction_time'] = $response[
'TIME'];
273 $_POST[
'transaction_status'] = $response[
'STATUS'];
274 $_POST[
'transaction_card_number'] = $response[
'CARDNO'];
275 $_POST[
'transaction_amount'] = $response[
'AMOUNT'];
276 $_POST[
'transaction_currency'] = $response[
'CURRENCY'];
278 $GLOBALS[
'SQ_SYSTEM']->broadcastTriggerEvent(
'trigger_event_ecommerce_payment_completed', $broadcaster);
307 if (is_null($bodycopy))
return;
309 $keywords = $bodycopy->getKeywords();
310 $replacements = Array();
311 foreach ($keywords as $word) {
314 $bodycopy->setKeywordReplacements($replacements);
317 if ($link_value ==
'display_format') {
319 $datapath = sq_web_path(
'data').
'/asset_types/payment_gateway_datacash/files';
322 if ($this->
attr(
'test_mode')) {
323 echo
'<h2 class="gateway-test-mode" style="color: white; background-color: #C00; padding: 5px">TEST MODE</h2>';
327 <script src=
"<?php echo $datapath; ?>/loader.js"></script>
329 var Loader =
new Loader(
'<?php echo $card; ?>',
'#FFFFFF',
'Processing Transaction...',
'<?php echo $datapath; ?>/loader.gif');
332 <form method=
"post" action=
"<?php echo $this->getURL(); ?>" onsubmit=
"Loader.show();">
334 $bodycopy->printBody();
338 $bodycopy->printBody();
352 $link = $GLOBALS[
'SQ_SYSTEM']->am->getLink($this->
id, SQ_LINK_TYPE_2,
'bodycopy', TRUE, $link_value);
353 if (empty($link))
return NULL;
354 $bodycopy = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($link[
'minorid'], $link[
'minor_type_code']);
370 if (!$card_info)
return FALSE;
372 $amount = $_SESSION[
'SQ_ECOM_AMOUNT'];
377 if (empty($amount)) {
378 $this->_setError(translate(
'datacash_amount_not_specified'));
380 $processor->setAmount($amount, $this->_getCurrency());
388 $processor->setMerchantReference(md5(session_id().time()));
390 $_SESSION[
'SQ_ECOM_REF_NO'] = $processor->getMerchantReference();
396 if (empty($card_info[
'number'])) {
397 $this->_setError(translate(
'datacash_card_number_not_specified'));
399 $card_info[
'number'] = str_replace(Array(
' ',
"\t"),
'', $card_info[
'number']);
400 $processor->setCardNumber($card_info[
'number']);
404 if ($this->_isValidDate(array_get_index($card_info,
'expiry_month',
''), array_get_index($card_info,
'expiry_year',
''))) {
405 $processor->setCardExpiryDate($card_info[
'expiry_month'], $card_info[
'expiry_year']);
407 $this->_setError(translate(
'datacash_expiry_date_invalid'));
411 if (!empty($card_info[
'start_month']) || !empty($card_info[
'start_year'])) {
412 if ($this->_isValidDate(array_get_index($card_info,
'start_month',
''), array_get_index($card_info,
'start_year',
''))) {
413 $processor->setCardStartDate($card_info[
'start_month'], $card_info[
'start_year']);
415 $this->_setError(translate(
'datacash_start_date_invalid'));
420 if (!empty($card_info[
'issue_number'])) {
421 if ($this->_isValidIssueNumber($card_info[
'issue_number'])) {
422 $processor->setCardIssueNumber($card_info[
'issue_number']);
424 $this->_setError(translate(
'datacash_issue_number_invalid'));
429 if (!empty($card_info[
'cv2'])) {
430 if ($this->_isValidCV2($card_info[
'cv2'])) {
431 $processor->setCardCV2($card_info[
'cv2']);
433 $this->_setError(translate(
'datacash_card_cv2_invalid'));
439 for ($i = 1; $i < 5; $i++) {
440 if (!empty($card_info[
'street_address'.$i])) {
441 $addr .= $card_info[
'street_address'.$i].
"\n";
442 $processor->setStreetAddress($i, $card_info[
'street_address'.$i]);
447 if (!empty($card_info[
'postcode'])) {
448 $addr .= $card_info[
'postcode'].
"\n";
449 $processor->setPostcode($card_info[
'postcode']);
453 $processor->setTransactionTypeAuth();
456 $nonthreed_card_types = $this->
attr(
'nonthreed_card_types');
457 $processor->setThreeDSecureParams($this->
attr(
'merchant_url'), $this->
attr(
'purchase_desc'), time(), empty($nonthreed_card_types)? Array() : explode(
'|', $nonthreed_card_types));
460 $policy = $this->
attr(
'avscv2_standard_policy');
462 $processor->setStandardPolicy($policy);
464 if (($policy == 2) || ($policy == 3) || ($policy == 6) || ($policy == 7)) {
465 if (empty($card_info[
'cv2'])) {
466 $this->_setError(translate(
'datacash_card_cv2_not_specified'));
470 if (($policy == 1) || ($policy == 3) || ($policy == 5) || ($policy == 7)) {
471 if (empty($card_info[
'street_address1']) && empty($card_info[
'street_address2']) && empty($card_info[
'street_address3']) && empty($card_info[
'street_address4'])) {
472 $this->_setError(translate(
'datacash_street_address_not_specified'));
475 if (empty($card_info[
'postcode'])) {
476 $this->_setError(translate(
'datacash_postcode_not_specified'));
487 $success = $processor->process();
490 $response = $processor->getResponse();
495 $_SESSION[
'SQ_ECOM_FORMATTED_CARD_NUMBER'] = $this->_getFormattedCardNumber($card_info[
'number']);
497 $_SESSION[
'SQ_ECOM_ORDER_BILLING_ADDR'] = $addr;
501 if ($success === 2) {
502 $this->_redirect_info = $response;
505 $this->_setTransactionResult($success, $response);
526 $success = $processor->authorize($datacash_ref, $pares);
529 $response = $processor->getResponse();
531 $this->_setTransactionResult($success, $response);
547 private function _setTransactionResult($success, $response)
549 if ($success === FALSE) {
550 $this->_setError($response[
'STATUS']);
552 if ($this->
attr(
'test_mode')) {
553 $response[
'STATUS'] =
'!!!ATTENTION!!! TEST MODE (transaction not performed) -- '.$response[
'STATUS'];
557 if (isset($_SESSION[
'SQ_ECOM_FORMATTED_CARD_NUMBER'])) {
558 $card_no = $_SESSION[
'SQ_ECOM_FORMATTED_CARD_NUMBER'];
559 unset($_SESSION[
'SQ_ECOM_FORMATTED_CARD_NUMBER']);
562 $response[
'CARDNO'] = $card_no;
563 $response[
'AMOUNT'] = $_SESSION[
'SQ_ECOM_AMOUNT'];
564 $response[
'CURRENCY'] = $this->_getCurrency();
567 if (isset($_SESSION[
'SQ_ECOM_ORDER_BILLING_ADDR'])) {
568 $billing_addr = $_SESSION[
'SQ_ECOM_ORDER_BILLING_ADDR'];
569 unset($_SESSION[
'SQ_ECOM_ORDER_BILLING_ADDR']);
571 $response[
'BILLING_ADDR'] = $billing_addr;
573 $_SESSION[
'SQ_ECOM_RESPONSE'] = $response;
587 private function _getFormattedCardNumber($card_number)
589 $card_no = $card_number;
590 $card_len = strlen($card_no);
591 if ($card_len == 16) {
592 $card_no =
'****-****-****-'.substr($card_no, -4);
594 $card_no = str_pad(substr($card_no, -4), $card_len,
'*', STR_PAD_LEFT);
614 if ($state ==
'SUCCESS') {
615 $back_url = array_get_index($_SESSION,
'SQ_ECOM_SUCCESS_URL');
616 }
else if ($state ==
'CANCEL') {
617 $back_url = array_get_index($_SESSION,
'SQ_ECOM_CANCEL_URL');
620 unset($_SESSION[
'SQ_ECOM_SUCCESS_URL']);
621 unset($_SESSION[
'SQ_ECOM_CANCEL_URL']);
623 if (is_null($back_url)) {
625 $this->_redirectParent($this->
getURL().
'?unknown_referer=1');
627 trigger_error(
'Unknown caller reference');
632 $this->_redirectParent($back_url);
634 header(
'Location: '.$back_url);
650 private function _redirectParent($url)
653 <script
type=
"text/javascript">
654 if (parent !=
self) {
655 parent.location =
"{$url}";
675 $card = $prefix.
'_card';
678 if ($this->
attr(
'test_mode')) {
680 $card_number =
'<select name="'.$card.
'[number]">';
681 foreach ($test_card_numbers as $number => $label) {
682 $card_number .=
'<option value="'.$number.
'" >'.$label.
'</option>';
684 $card_number .=
'</select>';
686 $card_number =
'<input name="'.$card.
'[number]" autocomplete="off" />';
704 $string =
'<input name="'.$card.
'[start_month]" size="2" autocomplete="off" />';
721 $string =
'<input name="'.$card.
'[start_year]" size="2" autocomplete="off" />';
738 $string =
'<input name="'.$card.
'[expiry_month]" size="2" autocomplete="off" />';
755 $string =
'<input name="'.$card.
'[expiry_year]" size="2" autocomplete="off" />';
772 $string =
'<input name="'.$card.
'[issue_number]" size="4" autocomplete="off" />';
789 $string =
'<input name="'.$card.
'[cv2]" size="4" autocomplete="off" />';
806 text_box($card.
'[street_address1]', $this->_getDefaultInputFromPassThroughAttribute(
'addr1_var_name'));
808 return ob_get_clean();
823 text_box($card.
'[street_address2]', $this->_getDefaultInputFromPassThroughAttribute(
'addr2_var_name'));
825 return ob_get_clean();
840 text_box($card.
'[street_address3]', $this->_getDefaultInputFromPassThroughAttribute(
'addr3_var_name'));
842 return ob_get_clean();
857 text_box($card.
'[street_address4]', $this->_getDefaultInputFromPassThroughAttribute(
'addr4_var_name'));
859 return ob_get_clean();
874 text_box($card.
'[postcode]', $this->_getDefaultInputFromPassThroughAttribute(
'postcode_var_name'));
876 return ob_get_clean();
889 $amount = array_get_index($_SESSION,
'SQ_ECOM_AMOUNT', 0);
904 return $this->_getCurrency();
918 return '<span class="payment-gateway-transaction-error">'.$this->getErrorMessage().
'</span>';
934 $button_text = $this->
attr(
'submit_text');
935 if (empty($button_text)) $button_text =
'Submit';
937 return '<input type="submit" value="'.$button_text.
'" />';
950 $button_text = $this->
attr(
'reset_text');
951 if (empty($button_text)) $button_text =
'Reset';
953 return '<input type="reset" value="'.$button_text.
'" />';
966 $button_text = $this->
attr(
'cancel_text');
967 if (empty($button_text)) $button_text =
'Cancel';
969 return '<input type="submit" name="'.$this->getPrefix().
'_action" value="'.$button_text.
'" />';
982 $md = md5($_SESSION[
'SQ_ECOM_REF_NO']);
985 <form name=
"PARequestForm" action=
"{$this->_redirect_info['ACS_URL']}" method=
"POST">
986 <input type=
"hidden" name=
"PaReq" value=
"{$this->_redirect_info['PAREQ_MESSAGE']}">
987 <input type=
"hidden" name=
"TermUrl" value=
"{$this->getURL()}">
988 <input type=
"hidden" name=
"MD" value=
"{$md}">
990 <iframe name=
"ACSframe" width=
"390" height=
"400" frameborder=
"0">
991 <b>Your browser does not support iframes</b>
993 <script type=
"text/javascript">
994 window.onload =
function()
996 document.PARequestForm.target =
"ACSframe";
997 document.PARequestForm.submit();
1014 private function _setError($err_message)
1016 $this->_tmp[
'is_error'] = TRUE;
1017 $this->_tmp[
'error_message'][] = $err_message;
1030 private function _isValidDate($month, $year)
1034 $two_digits_pattern =
'/^\d{2}$/';
1036 if (preg_match($two_digits_pattern, $month) && preg_match($two_digits_pattern, $year)) {
1038 if ((0 < $month) && ($month < 13)) {
1056 private function _isValidIssueNumber($issue_no)
1060 $pattern =
'/^\d{1,2}$/';
1062 if (preg_match($pattern, $issue_no)) {
1079 private function _isValidCV2($cv2)
1083 $pattern =
'/^\d{3,4}$/';
1085 if (preg_match($pattern, $cv2)) {
1094 private function _getPassThroughVariable($var_name, $default)
1096 if (is_null($this->_pass_through_vars)) {
1097 $this->_pass_through_vars = array_get_index($_SESSION,
'SQ_ECOM_PASS_THROUGH_VARS', Array());
1100 return array_get_index($this->_pass_through_vars, $var_name, $default);
1105 private function _getDefaultInputFromPassThroughAttribute($attr_name)
1108 $var_name = $this->
attr($attr_name);
1109 if (!empty($var_name)) {
1110 $result = $this->_getPassThroughVariable($var_name,
'');
1124 private function _getCurrency()
1126 return isset($_SESSION[
'SQ_ECOM_CURRENCY'])? $_SESSION[
'SQ_ECOM_CURRENCY'] : $this->
attr(
'currency');
1137 private function _unsetCurrency()
1139 if (isset($_SESSION[
'SQ_ECOM_CURRENCY'])) {
1140 unset($_SESSION[
'SQ_ECOM_CURRENCY']);
1154 return array_get_index($this->_tmp,
'is_error', FALSE);
1168 $errors = array_get_index($this->_tmp,
'error_message', Array());
1169 foreach ($errors as $error) {
1170 $err_message .=
"<li>$error </li>";
1173 return '<ul>'.$err_message.
'</ul>';