Version Notes
Release 1.0.0 added purchase & refund
Download this release
Release Info
Developer | Card Access Services |
Extension | CardAccessServices_Casmtp |
Version | 1.0.0 |
Comparing to | |
See all releases |
Version 1.0.0
- app/code/community/CardAccessServices/Casmtp/Helper/Data.php +30 -0
- app/code/community/CardAccessServices/Casmtp/Model/PaymentMethod.php +444 -0
- app/code/community/CardAccessServices/Casmtp/casmiscutil.php +84 -0
- app/code/community/CardAccessServices/Casmtp/casmtpprotocol.php +771 -0
- app/code/community/CardAccessServices/Casmtp/etc/config.xml +76 -0
- app/code/community/CardAccessServices/Casmtp/etc/system.xml +174 -0
- app/etc/modules/CardAccessServices_Casmtp.xml +12 -0
- package.xml +23 -0
app/code/community/CardAccessServices/Casmtp/Helper/Data.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Card Access Services CASMTP
|
4 |
+
*
|
5 |
+
* Copyright 2012 Card Access Services
|
6 |
+
*
|
7 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
+
* you may not use this file except in compliance with the License.
|
9 |
+
* You may obtain a copy of the License at
|
10 |
+
*
|
11 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12 |
+
*
|
13 |
+
* Unless required by applicable law or agreed to in writing, software
|
14 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
+
* See the License for the specific language governing permissions and
|
17 |
+
* limitations under the License.
|
18 |
+
*
|
19 |
+
* @author Card Access Services
|
20 |
+
* @copyright Copyright (c) 2012 Card Access Services (http://www.cardaccess.com.au)
|
21 |
+
* @license http://opensource.org/licenses/Apache-2.0 Apache Software License (ASL 2.0)
|
22 |
+
*/
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Data class for CASMTP - doesn't do anything additional at this point in time
|
26 |
+
*/
|
27 |
+
class CardAccessServices_Casmtp_Helper_Data extends Mage_Core_Helper_Abstract
|
28 |
+
{
|
29 |
+
}
|
30 |
+
?>
|
app/code/community/CardAccessServices/Casmtp/Model/PaymentMethod.php
ADDED
@@ -0,0 +1,444 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Card Access Services CASMTP
|
4 |
+
*
|
5 |
+
* Copyright 2012 Card Access Services
|
6 |
+
*
|
7 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
+
* you may not use this file except in compliance with the License.
|
9 |
+
* You may obtain a copy of the License at
|
10 |
+
*
|
11 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12 |
+
*
|
13 |
+
* Unless required by applicable law or agreed to in writing, software
|
14 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
+
* See the License for the specific language governing permissions and
|
17 |
+
* limitations under the License.
|
18 |
+
*
|
19 |
+
* @author Card Access Services
|
20 |
+
* @copyright Copyright (c) 2012 Card Access Services (http://www.cardaccess.com.au)
|
21 |
+
* @license http://opensource.org/licenses/Apache-2.0 Apache Software License (ASL 2.0)
|
22 |
+
*/
|
23 |
+
|
24 |
+
/* Load our CASMTP utility classes */
|
25 |
+
require_once('CardAccessServices/Casmtp/casmtpprotocol.php');
|
26 |
+
require_once('CardAccessServices/Casmtp/casmiscutil.php');
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Implements the gateway extension for transaction processing via the CASMTP method
|
30 |
+
*/
|
31 |
+
class CardAccessServices_Casmtp_Model_PaymentMethod extends Mage_Payment_Model_Method_Cc {
|
32 |
+
/**
|
33 |
+
* Unique payment identifier
|
34 |
+
*
|
35 |
+
* @var string
|
36 |
+
* @access protected
|
37 |
+
*/
|
38 |
+
protected $_code = 'casmtp';
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Whether we are a gateway extension
|
42 |
+
*
|
43 |
+
* @var boolean
|
44 |
+
* @access protected
|
45 |
+
*/
|
46 |
+
protected $_isGateway = true;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Whether we support the Authorize operation
|
50 |
+
*
|
51 |
+
* @var boolean
|
52 |
+
* @access protected
|
53 |
+
*/
|
54 |
+
protected $_canAuthorize = false;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Whether we support the Capture operation
|
58 |
+
*
|
59 |
+
* @var boolean
|
60 |
+
* @access protected
|
61 |
+
*/
|
62 |
+
protected $_canCapture = true;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Whether we support the CapturePartial operation
|
66 |
+
*
|
67 |
+
* @var boolean
|
68 |
+
* @access protected
|
69 |
+
*/
|
70 |
+
protected $_canCapturePartial = true;
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Whether we support the Void operation
|
74 |
+
*
|
75 |
+
* @var boolean
|
76 |
+
* @access protected
|
77 |
+
*/
|
78 |
+
protected $_canVoid = false;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Whether this extension can be used by cardholders during checkout
|
82 |
+
*
|
83 |
+
* @var boolean
|
84 |
+
* @access protected
|
85 |
+
*/
|
86 |
+
protected $_canUseCheckout = true;
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Whether this extension can be used by the admin interface
|
90 |
+
*
|
91 |
+
* @var boolean
|
92 |
+
* @access protected
|
93 |
+
*/
|
94 |
+
protected $_canUseInternal = true;
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Whether this extension can be used for multiple shipping
|
98 |
+
*
|
99 |
+
* @var boolean
|
100 |
+
* @access protected
|
101 |
+
*/
|
102 |
+
protected $_canUseForMultishipping = true;
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Whether this extension can be used for saving credit cards
|
106 |
+
*
|
107 |
+
* This is not in the base module, but for some reason most of the other payment methods
|
108 |
+
* declare it, so we'll do the same here just to be safe
|
109 |
+
*
|
110 |
+
* @var boolean
|
111 |
+
* @access protected
|
112 |
+
*/
|
113 |
+
protected $_canSaveCc = false;
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Whether we can do a refund
|
117 |
+
*
|
118 |
+
* @return boolean whether we can do a refund
|
119 |
+
* @access private
|
120 |
+
*/
|
121 |
+
public function canRefund() {
|
122 |
+
$version = Mage::getVersionInfo();
|
123 |
+
$major = intval ($version['major']);
|
124 |
+
$minor = intval ($version['minor']);
|
125 |
+
if ($major > 1) {
|
126 |
+
return true;
|
127 |
+
}
|
128 |
+
else if ($major == 1) {
|
129 |
+
return $minor > 5;
|
130 |
+
}
|
131 |
+
else {
|
132 |
+
return false;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Whether we can do a partial refund
|
138 |
+
*
|
139 |
+
* @return boolean whether we can do a partial refund
|
140 |
+
* @access private
|
141 |
+
*/
|
142 |
+
public function canRefundPartialPerInvoice() {
|
143 |
+
return $this->canRefund();
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Get the specified configuration value
|
148 |
+
*
|
149 |
+
* @param string $key name of the key
|
150 |
+
*
|
151 |
+
* @return string the configuration value
|
152 |
+
* @access private
|
153 |
+
*/
|
154 |
+
private function _getConfig($key) {
|
155 |
+
return Mage::getStoreConfig("payment/casmtp/" . $key);
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Get the merchant ID from the user configuration
|
160 |
+
*
|
161 |
+
* @return string the merchant ID
|
162 |
+
* @access private
|
163 |
+
*/
|
164 |
+
private function _getMerchantId() {
|
165 |
+
return $this->_getConfig("etx_merchant");
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Get the hash key from the user configuration
|
170 |
+
*
|
171 |
+
* @return string the hash key
|
172 |
+
* @access private
|
173 |
+
*/
|
174 |
+
private function _getHashKey() {
|
175 |
+
return $this->_getConfig("hash_auth");
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Figure out the gateway URL from the user configuration
|
180 |
+
*
|
181 |
+
* @return string the gateway URL
|
182 |
+
* @access private
|
183 |
+
*/
|
184 |
+
private function _getUrl() {
|
185 |
+
return $this->_getConfig('is_test')? Casmtp::TEST_URL: Casmtp::LIVE_URL;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Whether to log events into the system log file
|
190 |
+
*
|
191 |
+
* NB: If this is a high volume site then you will either want to turn this setting off or
|
192 |
+
* ensure log rotation is being used
|
193 |
+
*
|
194 |
+
* @return boolean whether to log events
|
195 |
+
* @access private
|
196 |
+
*/
|
197 |
+
private function _getLogEvents() {
|
198 |
+
return $this->_getConfig('log_events');
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Create a new preconfigured CASMTP proxy instance
|
203 |
+
*
|
204 |
+
* @return string the CASMTP proxy instance
|
205 |
+
* @access private
|
206 |
+
*/
|
207 |
+
private function _createCasmtpProxy() {
|
208 |
+
try {
|
209 |
+
return new CasmtpProxy($this->_getConfig('proxy_server_host'), $this->_getConfig('proxy_server_port'), $this->_getConfig('proxy_login_username'), Mage::helper('core')->decrypt($this->_getConfig('proxy_login_password')));
|
210 |
+
}
|
211 |
+
catch (Exception $e) {
|
212 |
+
Mage::log("$this->_code: proxy misconfigured");
|
213 |
+
Mage::throwException(Mage::helper('casmtp')->__($e->getMessage()));
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Create a new preconfigured CASMTP instance
|
219 |
+
*
|
220 |
+
* @return string the CASMTP instance
|
221 |
+
* @access private
|
222 |
+
*/
|
223 |
+
private function _createCasmtp() {
|
224 |
+
return new Casmtp($this->_getUrl(), $this->_createCasmtpProxy(), $this->_getMerchantId(), Mage::helper('core')->decrypt($this->_getHashKey()));
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Log the event
|
229 |
+
*
|
230 |
+
* @return void
|
231 |
+
* @access private
|
232 |
+
*/
|
233 |
+
private function _logPaymentEvent($payment, $msg) {
|
234 |
+
if ($this->_getLogEvents()) {
|
235 |
+
$cust_ref = CasMiscUtil::getCustRefFromPayment($payment);
|
236 |
+
Mage::log($this->_code . "[" . $cust_ref . "]:" . $msg);
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Retrieve audit number
|
242 |
+
*
|
243 |
+
* @param string $casmtp casmtp instance
|
244 |
+
* @param string $payment payment instance
|
245 |
+
* @param string $record_audit whether to record the audit number
|
246 |
+
*
|
247 |
+
* @return void
|
248 |
+
* @access private
|
249 |
+
*/
|
250 |
+
private function _getAuditNumber($casmtp, $payment, $record_audit = true) {
|
251 |
+
$cust_ref = CasMiscUtil::getCustRefFromPayment($payment);
|
252 |
+
|
253 |
+
/* Get the audit number, this is used to trace the transaction */
|
254 |
+
$this->_logPaymentEvent($payment, "getting audit number for order");
|
255 |
+
try {
|
256 |
+
$audit = $casmtp->getAudit();
|
257 |
+
}
|
258 |
+
catch (Exception $e) {
|
259 |
+
/*
|
260 |
+
* This almost always indicates a misconfiguration issue
|
261 |
+
*
|
262 |
+
* But on the up side no transaction has gone to the bank, so it is always safe to retry. Note that
|
263 |
+
* the error message from the exception is probably more confusing the end user than helpful, so we
|
264 |
+
* do not expose this (although we do log it)
|
265 |
+
*/
|
266 |
+
$this->_logPaymentEvent($payment, "error encountered: " . $e->getMessage());
|
267 |
+
Mage::throwException(Mage::helper('casmtp')->__("Error attempting transaction - please try again later"));
|
268 |
+
}
|
269 |
+
|
270 |
+
/*
|
271 |
+
* Record the audit number against the payment, if specified
|
272 |
+
*
|
273 |
+
* This can be quoted during support calls
|
274 |
+
*/
|
275 |
+
$this->_logPaymentEvent($payment, "got audit number $audit");
|
276 |
+
if ($record_audit) {
|
277 |
+
/* Fill in the transaction ID */
|
278 |
+
$payment->setCcTransId($audit);
|
279 |
+
//$payment->setLastTransId($audit);
|
280 |
+
$payment->setTransactionId($audit);
|
281 |
+
}
|
282 |
+
|
283 |
+
return $audit;
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Interpret the transaction result
|
288 |
+
*
|
289 |
+
* @param string $result the CASMTP transaction result
|
290 |
+
* @param string $payment payment instance
|
291 |
+
*
|
292 |
+
* @return void
|
293 |
+
* @access private
|
294 |
+
*/
|
295 |
+
private function _interpretTxnResult ($result, $payment) {
|
296 |
+
$cust_ref = CasMiscUtil::getCustRefFromPayment($payment);
|
297 |
+
|
298 |
+
/* Log the payment event for the benefit of debugging */
|
299 |
+
$this->_logPaymentEvent($payment, "scode = " . $result->GetStatusCode());
|
300 |
+
$this->_logPaymentEvent($payment, "rcode = " . $result->GetResponseCode());
|
301 |
+
$this->_logPaymentEvent($payment, "setl_date = " . $result->GetSettlementDate());
|
302 |
+
$this->_logPaymentEvent($payment, "auth_code = " . $result->GetAuthorizationCode());
|
303 |
+
$this->_logPaymentEvent($payment, "err_msg = " . $result->GetDiagnosticMessage());
|
304 |
+
|
305 |
+
/* Figure out the result */
|
306 |
+
if ($result->isApproved()) {
|
307 |
+
/* Hooray, transaction approved */
|
308 |
+
$this->_logPaymentEvent($payment, "transaction approved");
|
309 |
+
}
|
310 |
+
else {
|
311 |
+
/*
|
312 |
+
* Generate the error message
|
313 |
+
*
|
314 |
+
* We keep it in general terms to avoid confusing the end user - the real error and
|
315 |
+
* all relevant scodes etc have already been logged above for the administrator to inspect
|
316 |
+
*/
|
317 |
+
$errmsg = $result->isAbnormalResult()? "An error ocurred during transaction processing - please contact your site administrator for more details": "The transaction was declined - please try again with a different credit card";
|
318 |
+
$this->_logPaymentEvent($payment, "displayed message = " . $errmsg);
|
319 |
+
Mage::throwException(Mage::helper('casmtp')->__($errmsg));
|
320 |
+
}
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Validate the configuration
|
325 |
+
*
|
326 |
+
* This method is the only one where we expose inner configuration details - presumably the administrator
|
327 |
+
* will run through a test transaction to make sure all is configured before unleashing it to the internet!
|
328 |
+
*
|
329 |
+
* @return void
|
330 |
+
* @access public
|
331 |
+
*/
|
332 |
+
public function validate() {
|
333 |
+
/* Let the parent do it's usual validation */
|
334 |
+
parent::validate ();
|
335 |
+
|
336 |
+
/* Check the ETX merchant ID is present and numeric */
|
337 |
+
$merid = $this->_getMerchantId();
|
338 |
+
if (!is_numeric($merid)) {
|
339 |
+
Mage::log("$this->_code: merchant ID misconfigured as $merid");
|
340 |
+
Mage::throwException(Mage::helper('casmtp')->__('The "ETX Merchant ID" configuration value is not numeric, please set this to the value assigned by Card Access Services'));
|
341 |
+
}
|
342 |
+
|
343 |
+
/* Check the hash key is present */
|
344 |
+
$hash_key = $this->_getHashKey();
|
345 |
+
if (empty ($hash_key)) {
|
346 |
+
Mage::log("$this->_code: hash key misconfigured");
|
347 |
+
Mage::throwException(Mage::helper('casmtp')->__('The "Hash authentication" configuration value is empty, please set this to the value assigned by Card Access Services'));
|
348 |
+
}
|
349 |
+
|
350 |
+
/* Check the proxy settings are ok */
|
351 |
+
$proxy = $this->_createCasmtpProxy();
|
352 |
+
|
353 |
+
return $this;
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Perform a capture of the transaction
|
358 |
+
*
|
359 |
+
* @param string $payment payment instance
|
360 |
+
* @param float $amount amount to capture
|
361 |
+
*
|
362 |
+
* @return void
|
363 |
+
* @access public
|
364 |
+
*/
|
365 |
+
public function capture(Varien_Object $payment, $amount) {
|
366 |
+
$cust_ref = CasMiscUtil::getCustRefFromPayment($payment);
|
367 |
+
$this->_logPaymentEvent($payment, "capture invoked");
|
368 |
+
$casmtp = $this->_createCasmtp();
|
369 |
+
|
370 |
+
/* Get an audit number first */
|
371 |
+
$audit = $this->_getAuditNumber($casmtp, $payment);
|
372 |
+
|
373 |
+
/* Now do the actual purchase */
|
374 |
+
try {
|
375 |
+
$pan = $payment->getCcNumber();
|
376 |
+
$cvv = $payment->getCcCid();
|
377 |
+
$expiry = CasMiscUtil::formatExpiryFromPayment($payment);
|
378 |
+
$this->_logPaymentEvent($payment, "starting capture for $audit (pan = xxxx-" . $payment->getCcLast4() . ", amount = $amount)");
|
379 |
+
|
380 |
+
$result = $casmtp->purchase($audit, $pan, $expiry, $cvv, CasMiscUtil::flattenAmount($amount), $cust_ref);
|
381 |
+
}
|
382 |
+
catch (Exception $e) {
|
383 |
+
/* This usually indicates some kind of wierd networking issue */
|
384 |
+
Mage::log("$this->_code $cust_ref: error encountered: " . $e->getMessage());
|
385 |
+
Mage::throwException(Mage::helper('casmtp')->__("There was an error encountered while performing the transaction"));
|
386 |
+
}
|
387 |
+
|
388 |
+
/* Interpret the transaction result */
|
389 |
+
$this->_interpretTxnResult($result, $payment);
|
390 |
+
|
391 |
+
return $this;
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Perform a refund of the transaction
|
396 |
+
*
|
397 |
+
* @param string $payment payment instance
|
398 |
+
* @param float $amount amount to refund
|
399 |
+
*
|
400 |
+
* @return void
|
401 |
+
* @access public
|
402 |
+
*/
|
403 |
+
public function refund(Varien_Object $payment, $amount) {
|
404 |
+
$cust_ref = CasMiscUtil::getCustRefFromPayment($payment);
|
405 |
+
$this->_logPaymentEvent($payment, "refund invoked");
|
406 |
+
|
407 |
+
/*
|
408 |
+
* Filter out zero amounts just in case the care framework doesn't do this
|
409 |
+
*
|
410 |
+
* The gateway has no issue with this, but it's probably less confusing to the merchant if we block off
|
411 |
+
* the transaction immediately
|
412 |
+
*/
|
413 |
+
if (empty($amount)) {
|
414 |
+
Mage::throwException(Mage::helper('casmtp')->__("Can't refund a zero amount"));
|
415 |
+
}
|
416 |
+
|
417 |
+
/* Make sure we have the audit number of the previous transaction */
|
418 |
+
$old_audit = $payment->getLastTransId();
|
419 |
+
if (empty($old_audit)) {
|
420 |
+
Mage::throwException(Mage::helper('casmtp')->__("Previous transaction reference is empty - unable to locate previous transaction to refund"));
|
421 |
+
}
|
422 |
+
|
423 |
+
$casmtp = $this->_createCasmtp();
|
424 |
+
|
425 |
+
/* Get a new audit number */
|
426 |
+
$audit = $this->_getAuditNumber($casmtp, $payment);
|
427 |
+
|
428 |
+
/* Do the refund */
|
429 |
+
try {
|
430 |
+
$this->_logPaymentEvent($payment, "starting refund for $audit (pan = xxxx-" . $payment->getCcLast4() . ", amount = $amount)");
|
431 |
+
$result = $casmtp->refund($audit, $old_audit, CasMiscUtil::flattenAmount($amount));
|
432 |
+
}
|
433 |
+
catch (Exception $e) {
|
434 |
+
// This usually indicates some kind of wierd networking issue
|
435 |
+
$this->_logPaymentEvent($payment, "error encountered: " . $e->getMessage());
|
436 |
+
Mage::throwException(Mage::helper('casmtp')->__("There was an error encountered while performing the transaction"));
|
437 |
+
}
|
438 |
+
|
439 |
+
/* Interpret the transaction result */
|
440 |
+
$this->_interpretTxnResult($result, $payment);
|
441 |
+
|
442 |
+
return $this;
|
443 |
+
}
|
444 |
+
}
|
app/code/community/CardAccessServices/Casmtp/casmiscutil.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Card Access Services CASMTP
|
4 |
+
*
|
5 |
+
* Copyright 2012 Card Access Services
|
6 |
+
*
|
7 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
+
* you may not use this file except in compliance with the License.
|
9 |
+
* You may obtain a copy of the License at
|
10 |
+
*
|
11 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12 |
+
*
|
13 |
+
* Unless required by applicable law or agreed to in writing, software
|
14 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
+
* See the License for the specific language governing permissions and
|
17 |
+
* limitations under the License.
|
18 |
+
*
|
19 |
+
* @author Card Access Services
|
20 |
+
* @copyright Copyright (c) 2012 Card Access Services (http://www.cardaccess.com.au)
|
21 |
+
* @license http://opensource.org/licenses/Apache-2.0 Apache Software License (ASL 2.0)
|
22 |
+
*/
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Utility class
|
26 |
+
*
|
27 |
+
* Most of the methods are highly specific to this particular shopping cart
|
28 |
+
*/
|
29 |
+
class CasMiscUtil {
|
30 |
+
/**
|
31 |
+
* Flatten the supplied amount
|
32 |
+
*
|
33 |
+
* @param string $amt amount to flatten
|
34 |
+
*
|
35 |
+
* @return string the flattened amount
|
36 |
+
* @access public
|
37 |
+
*/
|
38 |
+
public static function flattenAmount($amt) {
|
39 |
+
return number_format($amt, 2, '', '');
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Format the expiry date from a payment object
|
44 |
+
*
|
45 |
+
* @param string $payment payment instance
|
46 |
+
*
|
47 |
+
* @return string the formatted expiry date
|
48 |
+
* @access public
|
49 |
+
*/
|
50 |
+
public static function formatExpiryFromPayment(&$payment) {
|
51 |
+
return sprintf("%02d%02d", $payment->getCcExpYear() % 100, $payment->getCcExpMonth());
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Get a suitable transaction reference from a payment object
|
56 |
+
*
|
57 |
+
* @param string $payment payment instance
|
58 |
+
*
|
59 |
+
* @return string the transaction reference
|
60 |
+
* @access private
|
61 |
+
*/
|
62 |
+
public static function getCustRefFromPayment($payment) {
|
63 |
+
return $payment->getOrder()->getIncrementId();
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Retrieve the value for a given key, throwing an exception if it doesn't exist
|
68 |
+
*
|
69 |
+
* @param string $reply the response array
|
70 |
+
* @param string $name the name of the expected key
|
71 |
+
* @param string $errmsg the error message to include in the exception if the key doesn't exist
|
72 |
+
*
|
73 |
+
* @return string the formatted expiry date
|
74 |
+
* @access public
|
75 |
+
*/
|
76 |
+
public static function getRequiredValue(&$reply, $name, $errmsg) {
|
77 |
+
if (isset($reply[$name])) {
|
78 |
+
return $reply[$name];
|
79 |
+
}
|
80 |
+
else {
|
81 |
+
throw new Exception($errmsg);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
}
|
app/code/community/CardAccessServices/Casmtp/casmtpprotocol.php
ADDED
@@ -0,0 +1,771 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Card Access Services CASMTP
|
4 |
+
*
|
5 |
+
* Copyright 2012 Card Access Services
|
6 |
+
*
|
7 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
+
* you may not use this file except in compliance with the License.
|
9 |
+
* You may obtain a copy of the License at
|
10 |
+
*
|
11 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12 |
+
*
|
13 |
+
* Unless required by applicable law or agreed to in writing, software
|
14 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
+
* See the License for the specific language governing permissions and
|
17 |
+
* limitations under the License.
|
18 |
+
*
|
19 |
+
* @author Card Access Services
|
20 |
+
* @copyright Copyright (c) 2012 Card Access Services (http://www.cardaccess.com.au)
|
21 |
+
* @license http://opensource.org/licenses/Apache-2.0 Apache Software License (ASL 2.0)
|
22 |
+
*/
|
23 |
+
|
24 |
+
/**
|
25 |
+
* This class implements exceptions which are pegged as CASMTP specific
|
26 |
+
*/
|
27 |
+
class CasmtpException extends Exception {
|
28 |
+
/**
|
29 |
+
* Constructor
|
30 |
+
*
|
31 |
+
* @param string $message the error message
|
32 |
+
* @param string $code the error code (optional)
|
33 |
+
* @param string $previous the previous exception (optional)
|
34 |
+
*
|
35 |
+
* @return void
|
36 |
+
* @access public
|
37 |
+
*/
|
38 |
+
public function __construct($message, $code = 0, Exception $previous = null) {
|
39 |
+
/* We don't do much here */
|
40 |
+
parent::__construct($message, $code, $previous);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* This class implements parsing of the CASMTP transaction result
|
46 |
+
*/
|
47 |
+
class CasmtpTxnResult {
|
48 |
+
/**
|
49 |
+
* The scode
|
50 |
+
*
|
51 |
+
* @var string
|
52 |
+
* @access private
|
53 |
+
*/
|
54 |
+
private $_statusCode;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* The response code
|
58 |
+
*
|
59 |
+
* @var string
|
60 |
+
* @access private
|
61 |
+
*/
|
62 |
+
private $_respCode;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Settlement date (YYMM)
|
66 |
+
*
|
67 |
+
* @var string
|
68 |
+
* @access private
|
69 |
+
*/
|
70 |
+
private $_setlDate;
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Authorization code
|
74 |
+
*
|
75 |
+
* @var string
|
76 |
+
* @access private
|
77 |
+
*/
|
78 |
+
private $_authCode;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* The request audit number
|
82 |
+
*
|
83 |
+
* @var string
|
84 |
+
* @access private
|
85 |
+
*/
|
86 |
+
private $_requestedAudit;
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Diagnostic message
|
90 |
+
*
|
91 |
+
* @var string
|
92 |
+
* @access private
|
93 |
+
*/
|
94 |
+
private $_msg;
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Constructor
|
98 |
+
*
|
99 |
+
* @param string $message error message
|
100 |
+
* @param string $code error code (optional)
|
101 |
+
* @param string $previous previous exception (optional)
|
102 |
+
*
|
103 |
+
* @return void
|
104 |
+
* @access public
|
105 |
+
*/
|
106 |
+
public function __construct($resp) {
|
107 |
+
$this->_statusCode = CasmtpTxnResult::_getDe048Kvp ("CAS.RESPONSE.STATUSCODE", $resp);
|
108 |
+
$this->_respCode = CasmtpTxnResult::_getKvp ("DE039", $resp);
|
109 |
+
$this->_setlDate = CasmtpTxnResult::_getKvp ("DE015", $resp);
|
110 |
+
$this->_authCode = CasmtpTxnResult::_getKvp ("DE038", $resp);
|
111 |
+
$this->_requestedAudit = CasmtpTxnResult::_getDe048Kvp("CAS.RESPONSE.AUDIT1", $resp);
|
112 |
+
$this->_msg = CasmtpTxnResult::_getDe048Kvp ("CAS.RESPONSE.MSG", $resp);
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Get the scode
|
117 |
+
*
|
118 |
+
* Typically blank, numeric (positive or negative)
|
119 |
+
*
|
120 |
+
* @return string status code
|
121 |
+
* @access public
|
122 |
+
*/
|
123 |
+
public function getStatusCode() {
|
124 |
+
return $this->_statusCode;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Get the response code
|
129 |
+
*
|
130 |
+
* Typically blank or 2 characters
|
131 |
+
*
|
132 |
+
* @return string response code
|
133 |
+
* @access public
|
134 |
+
*/
|
135 |
+
public function getResponseCode() {
|
136 |
+
return $this->_respCode;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Get the settlement date
|
141 |
+
*
|
142 |
+
* Typically blank or in YYMM format
|
143 |
+
*
|
144 |
+
* @return string settlement date
|
145 |
+
* @access public
|
146 |
+
*/
|
147 |
+
public function getSettlementDate() {
|
148 |
+
return $this->_setlDate;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
*
|
153 |
+
* Get the authorization code
|
154 |
+
*
|
155 |
+
* Format varies wildly, very bank specific, some banks insert trailing spaces (these are
|
156 |
+
* considered normal and part of the auth code)
|
157 |
+
*
|
158 |
+
* @return string authcode
|
159 |
+
* @access public
|
160 |
+
*/
|
161 |
+
public function getAuthorizationCode() {
|
162 |
+
return $this->_authCode;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
*
|
167 |
+
* Get the requested audit number
|
168 |
+
*
|
169 |
+
* NB: This field is only filled in when a new audit number is requested. It is possible to
|
170 |
+
* piggyback an audit number request onto a transaction operation (but the sample code doesn't
|
171 |
+
* take advantage of this)
|
172 |
+
*
|
173 |
+
* @return string the requested audit number
|
174 |
+
* @access public
|
175 |
+
*/
|
176 |
+
public function getRequestedAuditNumber() {
|
177 |
+
return $this->_requestedAudit;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Diagnostic message
|
182 |
+
*
|
183 |
+
* Common for it to be blank if casmtp doesn't want to add any additional commentary. This
|
184 |
+
* message is intended for developers only, it may be confusing or make no sense if exposed
|
185 |
+
* to an end user
|
186 |
+
*
|
187 |
+
* @return string diagnostic message
|
188 |
+
* @access public
|
189 |
+
*/
|
190 |
+
public function getDiagnosticMessage() {
|
191 |
+
return $this->_msg;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Whether the transaction was approved
|
196 |
+
*
|
197 |
+
* @return boolean if the transaction was approved
|
198 |
+
* @access public
|
199 |
+
*/
|
200 |
+
public function isApproved() {
|
201 |
+
return ($this->_statusCode === "0") && in_array ($this->_respCode, array ("00", "08", "10", "11", "16", "77"));
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Whether the transaction was not approved and not a normal decline (e.g. a time out)
|
206 |
+
*
|
207 |
+
* @return boolean if the transaction was not approved and not a normal decline (e.g. a time out)
|
208 |
+
* @access public
|
209 |
+
*/
|
210 |
+
public function isAbnormalResult() {
|
211 |
+
return $this->_statusCode !== "0";
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Utility method to retrieve value from the main KVPs
|
216 |
+
*
|
217 |
+
* @return string KVP value
|
218 |
+
* @access private
|
219 |
+
*/
|
220 |
+
private static function _getKvp($key, $kvp_array, $default = "") {
|
221 |
+
if (!array_key_exists($key, $kvp_array))
|
222 |
+
return $default;
|
223 |
+
else
|
224 |
+
return $kvp_array[$key];
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Utility method to retrieve value from the "miscellaneous" KVPs
|
229 |
+
*
|
230 |
+
* @return string KVP value
|
231 |
+
* @access public
|
232 |
+
*/
|
233 |
+
private static function _getDe048Kvp($key, $kvp_array) {
|
234 |
+
return CasmtpTxnResult::_getKvp($key, CasmtpTxnResult::_getKvp("DE048", $kvp_array, array()));
|
235 |
+
}
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* This class implements the casmtp proxy parameters
|
240 |
+
*
|
241 |
+
* NB: There is no online validation performed
|
242 |
+
*/
|
243 |
+
class CasmtpProxy {
|
244 |
+
/**
|
245 |
+
* Proxy server
|
246 |
+
*
|
247 |
+
* @var string
|
248 |
+
* @access private
|
249 |
+
*/
|
250 |
+
private $_server;
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Proxy server
|
254 |
+
*
|
255 |
+
* @var string
|
256 |
+
* @access private
|
257 |
+
*/
|
258 |
+
private $_login;
|
259 |
+
|
260 |
+
/**
|
261 |
+
* Constructor
|
262 |
+
*
|
263 |
+
* @param string $proxyHost proxy host
|
264 |
+
* @param string $proxyPort proxy port
|
265 |
+
* @param string $proxyUsername proxy username
|
266 |
+
* @param string $proxyPassword proxy password
|
267 |
+
*
|
268 |
+
* @return void
|
269 |
+
* @access public
|
270 |
+
*/
|
271 |
+
public function __construct($host = "", $port = "", $username = "", $password = "") {
|
272 |
+
/* Set defaults */
|
273 |
+
$this->_server = "";
|
274 |
+
$this->_login = "";
|
275 |
+
|
276 |
+
/* Set server if present */
|
277 |
+
if (!empty($host)) {
|
278 |
+
if (empty($port)) {
|
279 |
+
$port = "8080";
|
280 |
+
}
|
281 |
+
else {
|
282 |
+
if (!is_numeric($port)) {
|
283 |
+
throw new CasmtpException("Proxy port must be numeric, please check your configuration");
|
284 |
+
}
|
285 |
+
}
|
286 |
+
/* As per RFC 1123; we are actually a bit too loose, but this is ok as this is an admin only setting */
|
287 |
+
if (strpos($host, ':') !== FALSE) {
|
288 |
+
throw new CasmtpException("Proxy host is not allowed to contain a colon, please check your configuration");
|
289 |
+
}
|
290 |
+
$this->_server = $host . ':' . $port;
|
291 |
+
}
|
292 |
+
else {
|
293 |
+
if (!empty($port)) {
|
294 |
+
throw new CasmtpException("Proxy port has been specified, but host name was left empty, please check your configuration");
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
/* Set login if present */
|
299 |
+
if (!empty($username)) {
|
300 |
+
if (empty($this->_server)) {
|
301 |
+
throw new CasmtpException("Proxy login specified but the host was left empty, please check your configuration");
|
302 |
+
}
|
303 |
+
if (empty($password)) {
|
304 |
+
$password = "";
|
305 |
+
}
|
306 |
+
/* As per RFC 2068 */
|
307 |
+
if (strpos($username, ':') !== FALSE) {
|
308 |
+
throw new CasmtpException("Proxy username is not allowed to contain a colon, please check your configuration");
|
309 |
+
}
|
310 |
+
$this->_login = $username . ':' . $password;
|
311 |
+
}
|
312 |
+
else {
|
313 |
+
if (!empty($password)) {
|
314 |
+
throw new CasmtpException("Proxy password has been specified, but username was left empty, please check your configuration");
|
315 |
+
}
|
316 |
+
}
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Get the proxy server
|
321 |
+
*
|
322 |
+
* @return string proxy server
|
323 |
+
* @access public
|
324 |
+
*/
|
325 |
+
public function getServer() {
|
326 |
+
return $this->_server;
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* Get the proxy login
|
331 |
+
*
|
332 |
+
* @return string proxy login
|
333 |
+
* @access public
|
334 |
+
*/
|
335 |
+
public function getLogin() {
|
336 |
+
return $this->_login;
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
/**
|
341 |
+
* This class implements the request portion of the CASMTP protocol
|
342 |
+
*
|
343 |
+
* Currently only purchases and refunds are implemented - for other methods such as preauth, completion,
|
344 |
+
* card present transactions etc, see the CASMTP userguide
|
345 |
+
*/
|
346 |
+
class Casmtp {
|
347 |
+
/**
|
348 |
+
* The gateway URL
|
349 |
+
*
|
350 |
+
* @var string
|
351 |
+
* @access private
|
352 |
+
*/
|
353 |
+
private $_targetUrl;
|
354 |
+
|
355 |
+
/**
|
356 |
+
* The ETX merchant ID
|
357 |
+
*
|
358 |
+
* @var string
|
359 |
+
* @access private
|
360 |
+
*/
|
361 |
+
private $_merchantId;
|
362 |
+
|
363 |
+
/**
|
364 |
+
* The hash key
|
365 |
+
*
|
366 |
+
* @var string
|
367 |
+
* @access private
|
368 |
+
*/
|
369 |
+
private $_hashKey;
|
370 |
+
|
371 |
+
/**
|
372 |
+
* The proxy server
|
373 |
+
*
|
374 |
+
* @var string
|
375 |
+
* @access private
|
376 |
+
*/
|
377 |
+
private $_proxy;
|
378 |
+
|
379 |
+
/**
|
380 |
+
* The live gateway URL
|
381 |
+
*
|
382 |
+
* @var string
|
383 |
+
* @access public
|
384 |
+
* @const
|
385 |
+
*/
|
386 |
+
const LIVE_URL = 'https://etx.cardaccess.com.au/casmtp/casmtp.php';
|
387 |
+
|
388 |
+
/**
|
389 |
+
* The test gateway URL
|
390 |
+
*
|
391 |
+
* @var string
|
392 |
+
* @access public
|
393 |
+
* @const
|
394 |
+
*/
|
395 |
+
const TEST_URL = 'https://etx.cardaccess.com.au/casmtp/testcasmtp.php';
|
396 |
+
|
397 |
+
/**
|
398 |
+
* The default HTTP timeout
|
399 |
+
*
|
400 |
+
* @var string
|
401 |
+
* @access public
|
402 |
+
* @const
|
403 |
+
*/
|
404 |
+
const DEFAULT_HTTPS_TIMEOUT = 120;
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Constructor
|
408 |
+
*
|
409 |
+
* @param string $targetUrl URL of the gateway (typically LIVE_URL or TEST_URL)
|
410 |
+
* @param string $proxy Proxy server
|
411 |
+
* @param string $merchantId ETX merchant ID, as assigned by Card Access Services
|
412 |
+
* @param string $hashKey hash key, as assigned by Card Access Services
|
413 |
+
*
|
414 |
+
* @return void
|
415 |
+
* @access public
|
416 |
+
*/
|
417 |
+
public function __construct($targetUrl, $proxy, $merchantId, $hashKey) {
|
418 |
+
$this->_targetUrl = $targetUrl;
|
419 |
+
$this->_proxy = $proxy;
|
420 |
+
$this->_merchantId = $merchantId;
|
421 |
+
$this->_hashKey = $hashKey;
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Retrieve an audit number from the gateway
|
426 |
+
*
|
427 |
+
* An audit number is required before performing most operations. It is always safe to get
|
428 |
+
* another audit number if the first request timed out etc
|
429 |
+
*
|
430 |
+
* @return string audit number
|
431 |
+
* @access public
|
432 |
+
*/
|
433 |
+
public function getAudit() {
|
434 |
+
/* Send off the request */
|
435 |
+
$kvps = array('CAS.REQUEST.AUDIT' => '1');
|
436 |
+
$resp = $this->_sendRequest(
|
437 |
+
array(
|
438 |
+
'dataformat' => 'HTTP_AS2805',
|
439 |
+
'DE001' => '0800',
|
440 |
+
'DE042' => $this->_getFormattedMerchantId()
|
441 |
+
),
|
442 |
+
$kvps,
|
443 |
+
$this->_hashKey
|
444 |
+
);
|
445 |
+
|
446 |
+
/* Try to get at the audit number */
|
447 |
+
$result = new CasmtpTxnResult($resp);
|
448 |
+
$audit = $result->getRequestedAuditNumber();
|
449 |
+
|
450 |
+
/* Throw an exception if no audit number is present */
|
451 |
+
if ($audit == "" or $audit == "-1") {
|
452 |
+
$result = new CasmtpTxnResult($resp);
|
453 |
+
throw new CasmtpException ($result->getDiagnosticMessage());
|
454 |
+
}
|
455 |
+
|
456 |
+
/* Return the audit number for use in a follow up transaction */
|
457 |
+
return $audit;
|
458 |
+
}
|
459 |
+
|
460 |
+
/**
|
461 |
+
* Make a purchase
|
462 |
+
*
|
463 |
+
* Each purchase must be made against a unique audit number. While the customer reference
|
464 |
+
* is optional it is highly recommended. CVV is also optional, although banks may declined
|
465 |
+
* transactions sent without a CVV
|
466 |
+
*
|
467 |
+
* @param string $audit audit number retrieved using $this->getAudit()
|
468 |
+
* @param string $pan credit card number
|
469 |
+
* @param string $expiry expiry date in YYMM format
|
470 |
+
* @param string $cvv card verification value
|
471 |
+
* @param string $amt amount, in the minor denomination of the merchant account
|
472 |
+
* @param string $custRef customer reference field. Appears in the MMI reports
|
473 |
+
*
|
474 |
+
* @return void
|
475 |
+
* @access public
|
476 |
+
*/
|
477 |
+
public function purchase($audit, $pan, $expiry, $cvv, $amt, $custref = "") {
|
478 |
+
/* Send the request */
|
479 |
+
$kvps = array('CAS.AUDIT' => $audit);
|
480 |
+
if (!empty($custref)) {
|
481 |
+
$kvps['CAS.CUSTREF'] = $custref;
|
482 |
+
}
|
483 |
+
if (!empty($cvv)) {
|
484 |
+
$kvps['CAS.CARD.CVC'] = $cvv;
|
485 |
+
}
|
486 |
+
$resp = $this->_sendRequest(
|
487 |
+
array(
|
488 |
+
'dataformat' => 'HTTP_AS2805',
|
489 |
+
|
490 |
+
'DE001' => '0200',
|
491 |
+
'DE003' => '003000',
|
492 |
+
|
493 |
+
'DE042' => $this->_getFormattedMerchantId(),
|
494 |
+
|
495 |
+
'DE002' => $pan,
|
496 |
+
'DE014' => $expiry,
|
497 |
+
'DE004' => sprintf("%d", $amt)
|
498 |
+
),
|
499 |
+
$kvps,
|
500 |
+
$this->_hashKey
|
501 |
+
);
|
502 |
+
|
503 |
+
/* Interpret the request */
|
504 |
+
return new CasmtpTxnResult($resp);
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Refund a prior transaction
|
509 |
+
*
|
510 |
+
* Each refund must be made against a unique audit number. The audit number of the transaction
|
511 |
+
* to refund will also be required.
|
512 |
+
*
|
513 |
+
* We have encountered some banks in the past who do NOT allow merchants to perform refunds - if
|
514 |
+
* this is the case then the CASMTP refund operation will be rejected by the bank
|
515 |
+
*
|
516 |
+
* @param string $audit audit number retrieved using $this->getAudit()
|
517 |
+
* @param string $audit_to_refund audit number of transaction to refund
|
518 |
+
* @param string $amt amount to refund, in the minor denomination of the merchant account
|
519 |
+
* @param string $custRef customer reference field. Appears in the MMI reports
|
520 |
+
*
|
521 |
+
* @return void
|
522 |
+
* @access public
|
523 |
+
*/
|
524 |
+
public function refund($audit, $audit_to_refund, $amt, $custref = "") {
|
525 |
+
/* Send request */
|
526 |
+
$kvps = array('CAS.AUDIT' => $audit, 'CAS.REFUNDAUDIT' => $audit_to_refund);
|
527 |
+
if (!empty($custref))
|
528 |
+
$kvps['CAS.CUSTREF'] = $custref;
|
529 |
+
$resp = $this->_sendRequest(
|
530 |
+
array(
|
531 |
+
'dataformat' => 'HTTP_AS2805',
|
532 |
+
|
533 |
+
// Refund method
|
534 |
+
'DE001' => '0200',
|
535 |
+
'DE003' => '200030',
|
536 |
+
|
537 |
+
'DE042' => $this->_getFormattedMerchantId(),
|
538 |
+
|
539 |
+
'DE004' => sprintf("%d", $amt)
|
540 |
+
),
|
541 |
+
$kvps,
|
542 |
+
$this->_hashKey
|
543 |
+
);
|
544 |
+
|
545 |
+
/* Interpret result */
|
546 |
+
return new CasmtpTxnResult($resp);
|
547 |
+
}
|
548 |
+
|
549 |
+
/**
|
550 |
+
* Parses a transaction response into an array
|
551 |
+
*
|
552 |
+
* @param string $lines raw response text from CASMTP
|
553 |
+
* @param string $lineSep line separator to use
|
554 |
+
* @param string $kvpSep kvp separator to use
|
555 |
+
*
|
556 |
+
* @return array response kvps
|
557 |
+
* @access private
|
558 |
+
*/
|
559 |
+
private static function _explodeKvps($lines, $lineSep, $kvpSep) {
|
560 |
+
$resp = array();
|
561 |
+
$lines = explode($lineSep, $lines);
|
562 |
+
foreach ($lines as $line) {
|
563 |
+
$kvp = explode($kvpSep, $line, 2);
|
564 |
+
if (count($kvp) != 2)
|
565 |
+
continue;
|
566 |
+
$key = $kvp[0];
|
567 |
+
$value = $kvp[1];
|
568 |
+
$resp[$key] = $value;
|
569 |
+
}
|
570 |
+
return $resp;
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Encode a specific DE048 KVP for use in the hash calculation
|
575 |
+
*
|
576 |
+
* @param string $key key name
|
577 |
+
* @param string $value key value
|
578 |
+
*
|
579 |
+
* @return string the encoded DE048 KVP value
|
580 |
+
* @access private
|
581 |
+
*/
|
582 |
+
private static function _encodeDe048KvpForHash($key, $value) {
|
583 |
+
return $key . urlencode('=') . base64_encode($value);
|
584 |
+
}
|
585 |
+
|
586 |
+
/**
|
587 |
+
* Encode a specific DE048 KVP for use in the post
|
588 |
+
*
|
589 |
+
* @param string $key key name
|
590 |
+
* @param string $value key value
|
591 |
+
*
|
592 |
+
* @return string the encoded DE048 KVP value
|
593 |
+
* @access private
|
594 |
+
*/
|
595 |
+
private static function _encodeDe048KvpForPost($key, $value) {
|
596 |
+
return $key . '=' . base64_encode($value);
|
597 |
+
}
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Encode the entire DE048 KVP for use in the hash calculation
|
601 |
+
*
|
602 |
+
* @param string $de048 DE048 array
|
603 |
+
*
|
604 |
+
* @return string the encoded DE048 value
|
605 |
+
* @access private
|
606 |
+
*/
|
607 |
+
private static function _encodeDe048ForHash($de048) {
|
608 |
+
return array("DE048" => implode(urlencode ('&'), array_map('Casmtp::_encodeDe048KvpForHash', array_keys($de048), array_values($de048))));
|
609 |
+
}
|
610 |
+
|
611 |
+
/**
|
612 |
+
* Encode the entire DE048 KVP for use in the post
|
613 |
+
*
|
614 |
+
* @param string $de048 DE048 array
|
615 |
+
*
|
616 |
+
* @return string the encoded DE048 value
|
617 |
+
* @access private
|
618 |
+
*/
|
619 |
+
private static function _encodeDe048ForPost($de048) {
|
620 |
+
return array("DE048" => implode('&', array_map('Casmtp::_encodeDe048KvpForPost', array_keys($de048), array_values($de048))));
|
621 |
+
}
|
622 |
+
|
623 |
+
/**
|
624 |
+
* Send a CASMTP request
|
625 |
+
*
|
626 |
+
* @param string $postFieldsWithoutDe048 main post fields
|
627 |
+
* @param string $de048 supplementary post fields
|
628 |
+
*
|
629 |
+
* @return void
|
630 |
+
* @access private
|
631 |
+
*/
|
632 |
+
private function _sendRequest($postFieldsWithoutDe048, $de048)
|
633 |
+
{
|
634 |
+
/* POST fields for transaction */
|
635 |
+
$postFieldsForPost = array_merge($postFieldsWithoutDe048, Casmtp::_encodeDe048ForPost($de048));
|
636 |
+
|
637 |
+
/* Insert hash */
|
638 |
+
$this->_insertHash($postFieldsForPost, $postFieldsWithoutDe048, $de048);
|
639 |
+
|
640 |
+
/* Encode POST data */
|
641 |
+
$postData = http_build_query($postFieldsForPost);
|
642 |
+
|
643 |
+
/* Do POST */
|
644 |
+
/*
|
645 |
+
$opts = array(
|
646 |
+
'http' =>
|
647 |
+
array(
|
648 |
+
'method' => 'POST',
|
649 |
+
'header' => 'Content-type: application/x-www-form-urlencoded',
|
650 |
+
'content' => $postData
|
651 |
+
)
|
652 |
+
);
|
653 |
+
$context = stream_context_create($opts);
|
654 |
+
$lines = file_get_contents($this->_targetUrl, false, $context);
|
655 |
+
*/
|
656 |
+
|
657 |
+
/* CURL method */
|
658 |
+
$crl = curl_init();
|
659 |
+
|
660 |
+
/* Specify URL + automatically follow redirects */
|
661 |
+
curl_setopt($crl, CURLOPT_URL, $this->_targetUrl);
|
662 |
+
curl_setopt($crl, CURLOPT_FOLLOWLOCATION, 1);
|
663 |
+
|
664 |
+
/* Specify POST data + indicate we want the response back for processing */
|
665 |
+
curl_setopt($crl, CURLOPT_POST, 1);
|
666 |
+
curl_setopt($crl, CURLOPT_POSTFIELDS, $postData);
|
667 |
+
curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
|
668 |
+
|
669 |
+
/* Make sure we always use a fresh connection */
|
670 |
+
curl_setopt($crl, CURLOPT_FORBID_REUSE, 1);
|
671 |
+
curl_setopt($crl, CURLOPT_FRESH_CONNECT, 1);
|
672 |
+
|
673 |
+
/* Make sure we specify a sane timeout */
|
674 |
+
curl_setopt($crl, CURLOPT_CONNECTTIMEOUT, Casmtp::DEFAULT_HTTPS_TIMEOUT);
|
675 |
+
curl_setopt($crl, CURLOPT_TIMEOUT, Casmtp::DEFAULT_HTTPS_TIMEOUT);
|
676 |
+
|
677 |
+
/* Specify proxy, if required */
|
678 |
+
$proxyServer = $this->_proxy->getServer();
|
679 |
+
if (!empty($proxyServer)) {
|
680 |
+
curl_setopt($crl, CURLOPT_HTTPPROXYTUNNEL, true);
|
681 |
+
curl_setopt($crl, CURLOPT_PROXY, $proxyServer);
|
682 |
+
$proxyLogin = $this->_proxy->getLogin();
|
683 |
+
if (!empty($proxyLogin)) {
|
684 |
+
curl_setopt($crl, CURLOPT_PROXYUSERPWD, $proxyLogin);
|
685 |
+
}
|
686 |
+
}
|
687 |
+
|
688 |
+
/* Send POST */
|
689 |
+
$lines = curl_exec($crl);
|
690 |
+
|
691 |
+
/* Check the result */
|
692 |
+
$err = curl_errno($crl);
|
693 |
+
if ($err != CURLE_OK) {
|
694 |
+
throw new CasmtpException("CURL error performing transaction: " . curl_error($crl));
|
695 |
+
}
|
696 |
+
$status = curl_getinfo($crl, CURLINFO_HTTP_CODE);
|
697 |
+
if ($status != '200') {
|
698 |
+
throw new CasmtpException("HTTP error performing transaction: " . $status);
|
699 |
+
}
|
700 |
+
|
701 |
+
/* Decode main key value pairs */
|
702 |
+
$resp = Casmtp::_explodeKvps($lines, "\n", "=");
|
703 |
+
|
704 |
+
/* Further decode DE048 which has its own key value pairs (also base 64 encoded) */
|
705 |
+
if (array_key_exists("DE048", $resp)) {
|
706 |
+
/* Decode DE048 */
|
707 |
+
$items = Casmtp::_explodeKvps($resp["DE048"], "&", "=");
|
708 |
+
$resp["DE048"] = array ();
|
709 |
+
foreach ($items as $key=>$value) {
|
710 |
+
$resp["DE048"][$key] = base64_decode($value);
|
711 |
+
}
|
712 |
+
}
|
713 |
+
else {
|
714 |
+
/* Make sure DE048 always exists, even if it's just empty */
|
715 |
+
$resp["DE048"] = array();
|
716 |
+
}
|
717 |
+
|
718 |
+
/* Finalized response */
|
719 |
+
return $resp;
|
720 |
+
}
|
721 |
+
|
722 |
+
/**
|
723 |
+
* Insert hash value into the request
|
724 |
+
*
|
725 |
+
* NB: The time stamp of the server machine is embedded into the hash value. This value is checked
|
726 |
+
* by CASMTP - make sure your server clock is set correctly!
|
727 |
+
*
|
728 |
+
* @param string $destFields the destination for the hash KVPs
|
729 |
+
* @param string $postFields main post fields
|
730 |
+
* @param string $de048 supplementary post fields
|
731 |
+
*
|
732 |
+
* @return void
|
733 |
+
* @access private
|
734 |
+
*/
|
735 |
+
private function _insertHash(&$destFields, $postFields, $de048) {
|
736 |
+
$postFields_for_hash = array_merge($postFields, Casmtp::_encodeDe048ForHash($de048));
|
737 |
+
|
738 |
+
/* Insert the current UTC timestamp */
|
739 |
+
$timestamp = gmdate("Y/m/d G:i:s");
|
740 |
+
$destFields["CAS_SECURITY_TIMESTAMP"] = $timestamp;
|
741 |
+
$postFields_for_hash["CAS_SECURITY_TIMESTAMP"] = $timestamp;
|
742 |
+
|
743 |
+
/* Make sure the post fields are appended in the correct order */
|
744 |
+
$request_keys = array_keys($postFields_for_hash);
|
745 |
+
asort($request_keys);
|
746 |
+
|
747 |
+
/* Concatenate all the post fields together */
|
748 |
+
$temp_str = "";
|
749 |
+
foreach ($request_keys as $k) {
|
750 |
+
$v = $postFields_for_hash[$k];
|
751 |
+
if ($temp_str != "")
|
752 |
+
$temp_str .= "&";
|
753 |
+
$temp_str .= ($k . "=" . $v);
|
754 |
+
}
|
755 |
+
|
756 |
+
/* Calculate the hash */
|
757 |
+
$hash_value = hash_hmac("sha256", $temp_str, $this->_hashKey);
|
758 |
+
$destFields["CAS_SECURITY_TYPE"] = "Hash";
|
759 |
+
$destFields["CAS_SECURITY_VALUE"] = $hash_value;
|
760 |
+
}
|
761 |
+
|
762 |
+
/**
|
763 |
+
* Format the merchant ID for use in a CASMTP request
|
764 |
+
*
|
765 |
+
* @return string formatted merchant ID
|
766 |
+
* @access private
|
767 |
+
*/
|
768 |
+
private function _getFormattedMerchantId() {
|
769 |
+
return str_pad($this->_merchantId, 15, "0", STR_PAD_LEFT);
|
770 |
+
}
|
771 |
+
}
|
app/code/community/CardAccessServices/Casmtp/etc/config.xml
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<CardAccessServices_Casmtp>
|
5 |
+
<version>1.0.0</version>
|
6 |
+
</CardAccessServices_Casmtp>
|
7 |
+
</modules>
|
8 |
+
<frontend>
|
9 |
+
<routers>
|
10 |
+
<casmtp>
|
11 |
+
<use>standard</use>
|
12 |
+
<args>
|
13 |
+
<module>CardAccessServices_Casmtp</module>
|
14 |
+
<frontName>casmtp</frontName>
|
15 |
+
</args>
|
16 |
+
</casmtp>
|
17 |
+
</routers>
|
18 |
+
</frontend>
|
19 |
+
<global>
|
20 |
+
<blocks>
|
21 |
+
<casmtp>
|
22 |
+
<class>CardAccessServices_Casmtp_Block</class>
|
23 |
+
</casmtp>
|
24 |
+
</blocks>
|
25 |
+
<helpers>
|
26 |
+
<casmtp>
|
27 |
+
<class>CardAccessServices_Casmtp_Helper</class>
|
28 |
+
</casmtp>
|
29 |
+
</helpers>
|
30 |
+
<models>
|
31 |
+
<casmtp>
|
32 |
+
<class>CardAccessServices_Casmtp_Model</class>
|
33 |
+
</casmtp>
|
34 |
+
</models>
|
35 |
+
<resources>
|
36 |
+
<casmtp_setup>
|
37 |
+
<setup>
|
38 |
+
<module>CardAccessServices_Casmtp</module>
|
39 |
+
</setup>
|
40 |
+
<connection>
|
41 |
+
<use>core_setup></use>
|
42 |
+
</connection>
|
43 |
+
</casmtp_setup>
|
44 |
+
<casmtp_write>
|
45 |
+
<connection>
|
46 |
+
<use>core_write</use>
|
47 |
+
</connection>
|
48 |
+
</casmtp_write>
|
49 |
+
<casmtp_read>
|
50 |
+
<connection>
|
51 |
+
<use>core_read</use>
|
52 |
+
</connection>
|
53 |
+
</casmtp_read>
|
54 |
+
</resources>
|
55 |
+
</global>
|
56 |
+
<default>
|
57 |
+
<payment>
|
58 |
+
<casmtp>
|
59 |
+
<model>casmtp/paymentMethod</model>
|
60 |
+
<active>0</active>
|
61 |
+
<title>Credit Card (Casmtp)</title>
|
62 |
+
<order_status>processing</order_status>
|
63 |
+
<is_test>no</is_test>
|
64 |
+
<log_events>no</log_events>
|
65 |
+
<useccv>1</useccv>
|
66 |
+
<cctypes>VI,MC</cctypes>
|
67 |
+
<proxy_server_host/>
|
68 |
+
<proxy_server_port/>
|
69 |
+
<proxy_server_username/>
|
70 |
+
<proxy_server_password/>
|
71 |
+
<payment_action>authorize_capture</payment_action>
|
72 |
+
<allowspecific>0</allowspecific>
|
73 |
+
</casmtp>
|
74 |
+
</payment>
|
75 |
+
</default>
|
76 |
+
</config>
|
app/code/community/CardAccessServices/Casmtp/etc/system.xml
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<sections>
|
4 |
+
<payment>
|
5 |
+
<groups>
|
6 |
+
<casmtp translate="label">
|
7 |
+
<label>Card Access Services Casmtp</label>
|
8 |
+
<comment><![CDATA[<a href="http://www.cardaccess.com.au" target="_blank">For more information please visit http://www.cardaccess.com.au</a>]]></comment>
|
9 |
+
<sort_order>1</sort_order>
|
10 |
+
<show_in_default>1</show_in_default>
|
11 |
+
<show_in_website>1</show_in_website>
|
12 |
+
<show_in_store>1</show_in_store>
|
13 |
+
<fields>
|
14 |
+
<active translate="label">
|
15 |
+
<label>Enabled</label>
|
16 |
+
<comment><![CDATA[Enable this to allow transaction processing through Card Access Services using hosted payment pages]]></comment>
|
17 |
+
<frontend_type>select</frontend_type>
|
18 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
19 |
+
<sort_order>1</sort_order>
|
20 |
+
<show_in_default>1</show_in_default>
|
21 |
+
<show_in_website>1</show_in_website>
|
22 |
+
<show_in_store>1</show_in_store>
|
23 |
+
</active>
|
24 |
+
<title translate="label">
|
25 |
+
<label>Title</label>
|
26 |
+
<comment><![CDATA[The name that will be shown on the checkout pages]]></comment>
|
27 |
+
<frontend_type>text</frontend_type>
|
28 |
+
<sort_order>2</sort_order>
|
29 |
+
<show_in_default>1</show_in_default>
|
30 |
+
<show_in_website>1</show_in_website>
|
31 |
+
<show_in_store>1</show_in_store>
|
32 |
+
</title>
|
33 |
+
<is_test translate="label">
|
34 |
+
<label>Use Test Gateway</label>
|
35 |
+
<comment><![CDATA[Send transactions to the test gateway?<br><b>Please be sure to set this to "No" before going live</b>]]></comment>
|
36 |
+
<frontend_type>select</frontend_type>
|
37 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
38 |
+
<sort_order>3</sort_order>
|
39 |
+
<show_in_default>1</show_in_default>
|
40 |
+
<show_in_website>1</show_in_website>
|
41 |
+
<show_in_store>1</show_in_store>
|
42 |
+
</is_test>
|
43 |
+
<etx_merchant translate="label">
|
44 |
+
<label>ETX Merchant ID</label>
|
45 |
+
<comment><![CDATA[The ETX merchant ID<br><i>This must be set to the value assigned by Card Access Services</i>]]></comment>
|
46 |
+
<frontend_type>text</frontend_type>
|
47 |
+
<sort_order>4</sort_order>
|
48 |
+
<show_in_default>1</show_in_default>
|
49 |
+
<show_in_website>1</show_in_website>
|
50 |
+
<show_in_store>1</show_in_store>
|
51 |
+
</etx_merchant>
|
52 |
+
<hash_auth translate="label">
|
53 |
+
<label>Hash authentication</label>
|
54 |
+
<comment><![CDATA[The hash authentication password<br><i>This must be set to the value assigned by Card Access Services</i>]]></comment>
|
55 |
+
<frontend_type>password</frontend_type>
|
56 |
+
<backend_model>adminhtml/system_config_backend_encrypted</backend_model>
|
57 |
+
<sort_order>5</sort_order>
|
58 |
+
<show_in_default>1</show_in_default>
|
59 |
+
<show_in_website>1</show_in_website>
|
60 |
+
<show_in_store>1</show_in_store>
|
61 |
+
</hash_auth>
|
62 |
+
<useccv translate="label">
|
63 |
+
<label>Require CVV</label>
|
64 |
+
<comment><![CDATA[If this is enabled then the cardholder will be required to enter a CVV with each transaction. This may be mandated by your bank as a condition of transaction processing - double check with your bank for more details]]></comment>
|
65 |
+
<frontend_type>select</frontend_type>
|
66 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
67 |
+
<sort_order>6</sort_order>
|
68 |
+
<show_in_default>1</show_in_default>
|
69 |
+
<show_in_website>1</show_in_website>
|
70 |
+
<show_in_store>1</show_in_store>
|
71 |
+
</useccv>
|
72 |
+
<cctypes translate="label">
|
73 |
+
<label>Credit Card Types</label>
|
74 |
+
<comment><![CDATA[List the card types offered during checkout and on the admin screens<br><i>Not all credit card types will be supported by your merchant account; in addition, some card types may require an additional merchant account<br>Once your have setup the merchant account(s) with the relevant financial institutions, please let us know the details as well as which card types you wish to support, this will be configured at the same time as the ETX merchant above</i>]]></comment>
|
75 |
+
<frontend_type>multiselect</frontend_type>
|
76 |
+
<source_model>adminhtml/system_config_source_payment_cctype</source_model>
|
77 |
+
<sort_order>7</sort_order>
|
78 |
+
<show_in_default>1</show_in_default>
|
79 |
+
<show_in_website>1</show_in_website>
|
80 |
+
<show_in_store>0</show_in_store>
|
81 |
+
</cctypes>
|
82 |
+
<order_status translate="label">
|
83 |
+
<label>New order status</label>
|
84 |
+
<comment><![CDATA[Update the order to this status after the transaction has been completed]]></comment>
|
85 |
+
<frontend_type>select</frontend_type>
|
86 |
+
<source_model>adminhtml/system_config_source_order_status</source_model>
|
87 |
+
<sort_order>8</sort_order>
|
88 |
+
<show_in_default>1</show_in_default>
|
89 |
+
<show_in_website>1</show_in_website>
|
90 |
+
<show_in_store>1</show_in_store>
|
91 |
+
</order_status>
|
92 |
+
<sort_order translate="label">
|
93 |
+
<label>Sort order</label>
|
94 |
+
<comment><![CDATA[The relative order in which this payment method is shown. The lower the number, the higher up this payment method will appear in the list]]></comment>
|
95 |
+
<frontend_type>text</frontend_type>
|
96 |
+
<sort_order>9</sort_order>
|
97 |
+
<show_in_default>1</show_in_default>
|
98 |
+
<show_in_website>1</show_in_website>
|
99 |
+
<show_in_store>1</show_in_store>
|
100 |
+
</sort_order>
|
101 |
+
<allowspecific translate="label">
|
102 |
+
<label>Payment from applicable countries</label>
|
103 |
+
<comment><![CDATA[Whether to restrict cardholders to certain countries]]></comment>
|
104 |
+
<frontend_type>allowspecific</frontend_type>
|
105 |
+
<sort_order>10</sort_order>
|
106 |
+
<source_model>adminhtml/system_config_source_payment_allspecificcountries</source_model>
|
107 |
+
<show_in_default>1</show_in_default>
|
108 |
+
<show_in_website>1</show_in_website>
|
109 |
+
<show_in_store>1</show_in_store>
|
110 |
+
</allowspecific>
|
111 |
+
<specificcountry translate="label">
|
112 |
+
<label>Payment from specific countries</label>
|
113 |
+
<comment><![CDATA[Select the specific countries to restrict payments to<br><i>This only has effect if "Specific Countries" has been selected</i>]]></comment>
|
114 |
+
<frontend_type>multiselect</frontend_type>
|
115 |
+
<sort_order>11</sort_order>
|
116 |
+
<source_model>adminhtml/system_config_source_country</source_model>
|
117 |
+
<show_in_default>1</show_in_default>
|
118 |
+
<show_in_website>1</show_in_website>
|
119 |
+
<show_in_store>1</show_in_store>
|
120 |
+
<can_be_empty>1</can_be_empty>
|
121 |
+
</specificcountry>
|
122 |
+
<proxy_server_host translate="label">
|
123 |
+
<label>Proxy server host</label>
|
124 |
+
<comment><![CDATA[The hostname or IP address of the proxy server<br>This is only required if you are using a proxy, otherwise it can be left blank]]></comment>
|
125 |
+
<frontend_type>text</frontend_type>
|
126 |
+
<sort_order>12</sort_order>
|
127 |
+
<show_in_default>1</show_in_default>
|
128 |
+
<show_in_website>1</show_in_website>
|
129 |
+
<show_in_store>0</show_in_store>
|
130 |
+
</proxy_server_host>
|
131 |
+
<proxy_server_port translate="label">
|
132 |
+
<label>Proxy server port</label>
|
133 |
+
<comment><![CDATA[The port number of the proxy server<br>This is only required if you are using a proxy, otherwise it can be left blank. If a host is specified but the port number is left blank then the port number will default to 8080]]></comment>
|
134 |
+
<frontend_type>text</frontend_type>
|
135 |
+
<sort_order>13</sort_order>
|
136 |
+
<show_in_default>1</show_in_default>
|
137 |
+
<show_in_website>1</show_in_website>
|
138 |
+
<show_in_store>0</show_in_store>
|
139 |
+
</proxy_server_port>
|
140 |
+
<proxy_login_username translate="label">
|
141 |
+
<label>Proxy server username</label>
|
142 |
+
<comment><![CDATA[The username to use when accessing the proxy server<br>This is only required if you are using a proxy and it requires authentication, otherwise it can be left blank]]></comment>
|
143 |
+
<frontend_type>text</frontend_type>
|
144 |
+
<sort_order>14</sort_order>
|
145 |
+
<show_in_default>1</show_in_default>
|
146 |
+
<show_in_website>1</show_in_website>
|
147 |
+
<show_in_store>0</show_in_store>
|
148 |
+
</proxy_login_username>
|
149 |
+
<proxy_login_password translate="label">
|
150 |
+
<label>Proxy server password</label>
|
151 |
+
<comment><![CDATA[The password to use when accessing the proxy server<br>This is only required if you are using a proxy and it requires a password, otherwise it can be left blank]]></comment>
|
152 |
+
<frontend_type>password</frontend_type>
|
153 |
+
<backend_model>adminhtml/system_config_backend_encrypted</backend_model>
|
154 |
+
<sort_order>15</sort_order>
|
155 |
+
<show_in_default>1</show_in_default>
|
156 |
+
<show_in_website>1</show_in_website>
|
157 |
+
<show_in_store>0</show_in_store>
|
158 |
+
</proxy_login_password>
|
159 |
+
<log_events translate="label">
|
160 |
+
<label>Log Events</label>
|
161 |
+
<comment><![CDATA[Log each payment event into the system log (if enabled)?]]></comment>
|
162 |
+
<frontend_type>select</frontend_type>
|
163 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
164 |
+
<sort_order>16</sort_order>
|
165 |
+
<show_in_default>1</show_in_default>
|
166 |
+
<show_in_website>1</show_in_website>
|
167 |
+
<show_in_store>1</show_in_store>
|
168 |
+
</log_events>
|
169 |
+
</fields>
|
170 |
+
</casmtp>
|
171 |
+
</groups>
|
172 |
+
</payment>
|
173 |
+
</sections>
|
174 |
+
</config>
|
app/etc/modules/CardAccessServices_Casmtp.xml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<CardAccessServices_Casmtp>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</CardAccessServices_Casmtp>
|
8 |
+
<depends>
|
9 |
+
<Mage_Payment/>
|
10 |
+
</depends>
|
11 |
+
</modules>
|
12 |
+
</config>
|
package.xml
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>CardAccessServices_Casmtp</name>
|
4 |
+
<version>1.0.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/Apache-2.0">Apache Software License (ASL)</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Merchant hosted transaction processing using the Card Access Services gateway</summary>
|
10 |
+
<description>This gateway extension allows you to process merchant hosted transactions through the Card Access Services payment
|
11 |
+

|
12 |
+
You will need a compatible merchant account with any of the numerous financial institutions we are connected to worldwide, as well as an account with us
|
13 |
+

|
14 |
+
Please contact info@cardaccess.com.au (http://www.cardaccess.com.au) for more information
|
15 |
+
</description>
|
16 |
+
<notes>Release 1.0.0 added purchase & refund</notes>
|
17 |
+
<authors><author><name>Card Access Services</name><user>cardaccessservices</user><email>techadmin@rt.cardaccess.com.au</email></author></authors>
|
18 |
+
<date>2012-06-26</date>
|
19 |
+
<time>23:42:33</time>
|
20 |
+
<contents><target name="mageetc"><dir name="modules"><file name="CardAccessServices_Casmtp.xml" hash="78d9b601cf91a93dddc4356edff54870"/></dir></target><target name="magecommunity"><dir name="CardAccessServices"><dir name="Casmtp"><dir name="Helper"><file name="Data.php" hash="018d64d703c1eb68c28068c0de721cbc"/></dir><dir name="Model"><file name="PaymentMethod.php" hash="3c3b66c09004e2a4d8b9dcdcee7d2013"/></dir><file name="casmiscutil.php" hash="23e8224f830b7041a69290d642db27e1"/><file name="casmtpprotocol.php" hash="09dc63f173f10e2fdd4b8c8cf02d53bf"/><dir name="etc"><file name="config.xml" hash="e3da56d0f4bee8f61bd7aa365d15301f"/><file name="system.xml" hash="814ae364c5b84f5949601a4a8693e0a3"/></dir></dir></dir></target></contents>
|
21 |
+
<compatible/>
|
22 |
+
<dependencies><required><php><min>5.1.2</min><max>6.0.0</max></php><extension><name>hash</name><min>1.1</min><max></max></extension></required></dependencies>
|
23 |
+
</package>
|