| 1 |
<?php
|
| 2 |
// $Id$
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Integrates the NAB Transact Direct XML API for processing CC payments.
|
| 7 |
*
|
| 8 |
* Sponsored by Sourdough Companion - http://sourdough.com
|
| 9 |
*/
|
| 10 |
|
| 11 |
|
| 12 |
/**
|
| 13 |
* Implementation of hook_payment_gateway().
|
| 14 |
*/
|
| 15 |
function uc_nab_transact_payment_gateway() {
|
| 16 |
$gateways = array();
|
| 17 |
|
| 18 |
$gateways[] = array(
|
| 19 |
'id' => 'nab_transact',
|
| 20 |
'title' => t('NAB Transact'),
|
| 21 |
'description' => t('Process credit card payments using the NAB Transact XML API.'),
|
| 22 |
'settings' => 'uc_nab_transact_settings_form',
|
| 23 |
'credit' => 'uc_nab_transact_charge',
|
| 24 |
);
|
| 25 |
|
| 26 |
return $gateways;
|
| 27 |
}
|
| 28 |
|
| 29 |
// Displays the fields for the NAB Transact settings.
|
| 30 |
function uc_nab_transact_settings_form() {
|
| 31 |
$form['uc_nab_currency'] = array(
|
| 32 |
'#type' => 'textfield',
|
| 33 |
'#title' => t('Currency code'),
|
| 34 |
'#description' => t('Defaults to AUD; support for other currencies is not known.'),
|
| 35 |
'#default_value' => variable_get('uc_nab_currency', 'AUD'),
|
| 36 |
);
|
| 37 |
$form['uc_nab_transact_po_prefix'] = array(
|
| 38 |
'#type' => 'textfield',
|
| 39 |
'#title' => t('PO prefix'),
|
| 40 |
'#description' => t('Enter a string to place before the order ID when specifying a PO number through NAB Transact.'),
|
| 41 |
'#default_value' => variable_get('uc_nab_transact_po_prefix', ''),
|
| 42 |
);
|
| 43 |
|
| 44 |
$form['uc_nab_transact_xml_settings'] = array(
|
| 45 |
'#type' => 'fieldset',
|
| 46 |
'#title' => t('XML API settings'),
|
| 47 |
'#description' => t('This module currently only integrates the XML API provided by NAB Transact for processing credit cards. You must fill in the appropriate information below and ensure you have SSL enabled for the site.'),
|
| 48 |
);
|
| 49 |
$form['uc_nab_transact_xml_settings']['uc_nab_xml_merchant_id'] = array(
|
| 50 |
'#type' => 'textfield',
|
| 51 |
'#title' => t('Merchant ID'),
|
| 52 |
'#description' => t('The 7 character merchant ID for Credit Card transactions, eg: "ABC0001".'),
|
| 53 |
'#default_value' => variable_get('uc_nab_xml_merchant_id', ''),
|
| 54 |
);
|
| 55 |
$form['uc_nab_transact_xml_settings']['uc_nab_xml_password'] = array(
|
| 56 |
'#type' => 'textfield',
|
| 57 |
'#title' => t('Password'),
|
| 58 |
'#description' => t('Your password for making XML API requests.'),
|
| 59 |
'#default_value' => variable_get('uc_nab_xml_password', ''),
|
| 60 |
);
|
| 61 |
$form['uc_nab_transact_xml_settings']['uc_nab_xml_mode'] = array(
|
| 62 |
'#type' => 'select',
|
| 63 |
'#title' => t('Transaction mode'),
|
| 64 |
'#description' => t('Transaction mode used when sending requests.'),
|
| 65 |
'#options' => array(
|
| 66 |
'test' => t('Test'),
|
| 67 |
'live' => t('Live'),
|
| 68 |
),
|
| 69 |
'#default_value' => variable_get('uc_nab_xml_mode', 'test'),
|
| 70 |
);
|
| 71 |
$form['uc_nab_transact_xml_settings']['uc_nab_xml_txn_type'] = array(
|
| 72 |
'#type' => 'select',
|
| 73 |
'#title' => t('Transaction type'),
|
| 74 |
'#description' => t('Specify the transaction type for XML API transactions.'),
|
| 75 |
'#options' => array(
|
| 76 |
'0' => t('Standard Payment'),
|
| 77 |
// '10' => t('Preauthorise'),
|
| 78 |
// '11' => t('Preauth Complete'),
|
| 79 |
),
|
| 80 |
'#default_value' => variable_get('uc_nab_xml_txn_type', '0'),
|
| 81 |
);
|
| 82 |
|
| 83 |
return $form;
|
| 84 |
}
|
| 85 |
|
| 86 |
function uc_nab_transact_charge($order_id, $amount, $data) {
|
| 87 |
global $user;
|
| 88 |
|
| 89 |
$order = uc_order_load($order_id);
|
| 90 |
|
| 91 |
// Pad the expiration date with a 0 for single digit months.
|
| 92 |
if (strlen($order->payment_details['cc_exp_month']) == 1) {
|
| 93 |
$order->payment_details['cc_exp_month'] = '0'. $order->payment_details['cc_exp_month'];
|
| 94 |
}
|
| 95 |
|
| 96 |
$data = array(
|
| 97 |
'txnType' => variable_get('uc_nab_xml_txn_type', '0'),
|
| 98 |
'txnSource' => 23,
|
| 99 |
'amount' => $amount * 100,
|
| 100 |
'currency' => variable_get('uc_nab_currency', 'AUD'),
|
| 101 |
'purchaseOrderNo' => uc_nab_transact_po($order_id),
|
| 102 |
'CreditCardInfo' => array(
|
| 103 |
'cardNumber' => $order->payment_details['cc_number'],
|
| 104 |
'expiryDate' => $order->payment_details['cc_exp_month'] .'/'. substr((string)$order->payment_details['cc_exp_year'], 2),
|
| 105 |
),
|
| 106 |
);
|
| 107 |
|
| 108 |
if (variable_get('uc_credit_cvv_enabled', TRUE)) {
|
| 109 |
$data['CreditCardInfo']['cvv'] = $order->payment_details['cc_cvv'];
|
| 110 |
}
|
| 111 |
|
| 112 |
// Get the next message ID.
|
| 113 |
$message_id = variable_get('uc_nab_xml_message_id', 1);
|
| 114 |
variable_set('uc_nab_xml_message_id', $message_id + 1);
|
| 115 |
|
| 116 |
// Build the post XML from the data array.
|
| 117 |
$post_data = uc_nab_transact_xml('Payment', $data, $message_id);
|
| 118 |
|
| 119 |
// Build the URL where we'll send the request.
|
| 120 |
$url = 'https://transact.nab.com.au/'. variable_get('uc_nab_xml_mode', 'test') .'/xmlapi/payment';
|
| 121 |
|
| 122 |
// Get the response of our payment request.
|
| 123 |
$response = drupal_http_request($url, array('Content-Type' => 'text/xml'), 'POST', $post_data);
|
| 124 |
|
| 125 |
// Include the XML parser for PHP 4 compatibility.
|
| 126 |
require_once(drupal_get_path('module', 'uc_store') .'/includes/simplexml.php');
|
| 127 |
|
| 128 |
// Create the XML object and parse the response string.
|
| 129 |
$xml = new JSimpleXML;
|
| 130 |
$xml->loadString($response->data);
|
| 131 |
|
| 132 |
// Check to make sure the response parses and payment passed properly.
|
| 133 |
if (isset($xml->document->status[0]->statuscode[0]) && $xml->document->status[0]->statuscode[0]->data() != '000') {
|
| 134 |
$approval = 'No';
|
| 135 |
$responsecode = $xml->document->status[0]->statuscode[0]->data();
|
| 136 |
$responsetext = $xml->document->status[0]->statusdescription[0]->data();
|
| 137 |
}
|
| 138 |
elseif (isset($xml->document->payment[0]->txnlist[0]->txn[0]->approved[0])) {
|
| 139 |
$approval = $xml->document->payment[0]->txnlist[0]->txn[0]->approved[0]->data();
|
| 140 |
$responsecode = $xml->document->payment[0]->txnlist[0]->txn[0]->responsecode[0]->data();
|
| 141 |
$responsetext = $xml->document->payment[0]->txnlist[0]->txn[0]->responsetext[0]->data();
|
| 142 |
$charged = $xml->document->payment[0]->txnlist[0]->txn[0]->amount[0]->data() / 100;
|
| 143 |
$txnid = $xml->document->payment[0]->txnlist[0]->txn[0]->txnid[0]->data();
|
| 144 |
}
|
| 145 |
else {
|
| 146 |
// Otherwise supply some default values.
|
| 147 |
$approval = 'No';
|
| 148 |
$responsecode = 'x';
|
| 149 |
$responsetext = t('Failed to parse the XML API request or response.');
|
| 150 |
|
| 151 |
// Log the trouble string to the watchdog.
|
| 152 |
watchdog('uc_nab_transact', t('Failed XML parse response:<br/>@xml', array('@xml' => $response->data)), WATCHDOG_ERROR);
|
| 153 |
}
|
| 154 |
|
| 155 |
if ($approval != 'Yes') {
|
| 156 |
$message = t('Credit card declined: !amount', array('!amount' => uc_currency_format($amount)));
|
| 157 |
|
| 158 |
$result = array(
|
| 159 |
'success' => FALSE,
|
| 160 |
'comment' => t('Credit card payment declined: @text', array('@text' => $responsetext)),
|
| 161 |
'message' => t('Credit card payment declined: @text', array('@text' => $responsetext)),
|
| 162 |
'uid' => $user->uid,
|
| 163 |
);
|
| 164 |
}
|
| 165 |
else {
|
| 166 |
$message = t('Credit card charged: !amount', array('!amount' => uc_currency_format($charged)))
|
| 167 |
.'<br />'. t('NAB Transact Txn ID: @txnid', array('@txnid' => $txnid));
|
| 168 |
|
| 169 |
$result = array(
|
| 170 |
'success' => TRUE,
|
| 171 |
'comment' => t('NAB Transact Txn ID: @txnid<br/>Approval code: @code', array('@txnid' => $txnid, '@code' => $responsecode)),
|
| 172 |
'message' => t('NAB Transact Txn ID: @txnid<br/>Approval code: @code', array('@txnid' => $txnid, '@code' => $responsecode)),
|
| 173 |
'data' => array('TxnID' => $txnid),
|
| 174 |
'uid' => $user->uid,
|
| 175 |
);
|
| 176 |
}
|
| 177 |
|
| 178 |
$message .= '<br />'. t('Response code: @code - @text', array('@code' => $responsecode, '@text' => $responsetext));
|
| 179 |
|
| 180 |
uc_order_comment_save($order_id, $user->uid, $message, 'admin');
|
| 181 |
|
| 182 |
return $result;
|
| 183 |
}
|
| 184 |
|
| 185 |
function uc_nab_transact_xml($type, $data, $message_id) {
|
| 186 |
if ($type !== 'Payment' && $type !== 'Echo') {
|
| 187 |
return;
|
| 188 |
}
|
| 189 |
|
| 190 |
$xml = '<?xml version="1.0" encoding="UTF-8"?><NABTransactMessage>';
|
| 191 |
|
| 192 |
$xml .= uc_nab_transact_message_info($message_id);
|
| 193 |
$xml .= uc_nab_transact_merchant_info();
|
| 194 |
|
| 195 |
$xml .= '<RequestType>'. $type .'</RequestType>';
|
| 196 |
|
| 197 |
if ($type == 'Payment') {
|
| 198 |
$xml .= uc_nab_transact_payment_xml($data);
|
| 199 |
}
|
| 200 |
|
| 201 |
$xml .= '</NABTransactMessage>';
|
| 202 |
|
| 203 |
return $xml;
|
| 204 |
}
|
| 205 |
|
| 206 |
function uc_nab_transact_message_info($message_id) {
|
| 207 |
return '<MessageInfo><messageID>'. substr(md5($message_id), 0, 30)
|
| 208 |
.'</messageID><messageTimestamp>'. uc_nab_transact_timestamp()
|
| 209 |
.'</messageTimestamp><timeoutValue>60</timeoutValue>'
|
| 210 |
.'<apiVersion>xml-4.2</apiVersion></MessageInfo>';
|
| 211 |
}
|
| 212 |
|
| 213 |
function uc_nab_transact_merchant_info() {
|
| 214 |
return '<MerchantInfo><merchantID>'. variable_get('uc_nab_xml_merchant_id', '')
|
| 215 |
.'</merchantID><password>'. variable_get('uc_nab_xml_password', '')
|
| 216 |
.'</password></MerchantInfo>';
|
| 217 |
}
|
| 218 |
|
| 219 |
/**
|
| 220 |
* Build the XML for the payment element.
|
| 221 |
*
|
| 222 |
* NAB Transact currently only supports 1 payment at a time, hence the hard
|
| 223 |
* coded count and ID.
|
| 224 |
*/
|
| 225 |
function uc_nab_transact_payment_xml($data) {
|
| 226 |
$xml = '<Payment><TxnList count="1"><Txn ID="1">';
|
| 227 |
|
| 228 |
foreach ($data as $key => $value) {
|
| 229 |
if (is_array($value)) {
|
| 230 |
$xml .= '<'. $key .'>';
|
| 231 |
foreach ($value as $arr_key => $arr_value) {
|
| 232 |
$xml .= '<'. $arr_key .'>'. $arr_value .'</'. $arr_key .'>';
|
| 233 |
}
|
| 234 |
$xml .= '</'. $key .'>';
|
| 235 |
}
|
| 236 |
else {
|
| 237 |
$xml .= '<'. $key .'>'. $value .'</'. $key .'>';
|
| 238 |
}
|
| 239 |
}
|
| 240 |
|
| 241 |
$xml .= '</Txn></TxnList></Payment>';
|
| 242 |
|
| 243 |
return $xml;
|
| 244 |
}
|
| 245 |
|
| 246 |
function uc_nab_transact_timestamp($time = NULL) {
|
| 247 |
if (empty($time)) {
|
| 248 |
$time = time();
|
| 249 |
}
|
| 250 |
|
| 251 |
// Return a formatted GMT timestamp.
|
| 252 |
return date('YdmHis000000+000', $time);
|
| 253 |
}
|
| 254 |
|
| 255 |
function uc_nab_transact_po($order_id) {
|
| 256 |
return variable_get('uc_nab_transact_po_prefix', '') . $order_id;
|
| 257 |
}
|
| 258 |
|