Version Notes
Implements 3D Secure payment feature.
Download this release
Release Info
Developer | Demac Media |
Extension | 666999 |
Version | 0.3.9 |
Comparing to | |
See all releases |
Code changes from version 0.3.8 to 0.3.9
- app/code/community/Demac/.DS_Store +0 -0
- app/code/community/Demac/Optimal/Block/Navigation.php +15 -0
- app/code/community/Demac/Optimal/Helper/Data.php +103 -54
- app/code/community/Demac/Optimal/Model/Creditcard.php +7 -0
- app/code/community/Demac/Optimal/Model/Hosted/Client.php +49 -19
- app/code/community/Demac/Optimal/Model/Method/Hosted.php +177 -73
- app/code/community/Demac/Optimal/Model/Observer.php +1 -0
- app/code/community/Demac/Optimal/Test/Model/Hosted/Client.php +16 -0
- app/code/community/Demac/Optimal/Test/Model/Method/Hosted.php +17 -0
- app/code/community/Demac/Optimal/Test/Model/Observer.php +9 -0
- app/code/community/Demac/Optimal/controllers/Frontend/OptimalController.php +14 -0
- app/code/community/Demac/Optimal/controllers/HandlerController.php +154 -0
- app/code/community/Demac/Optimal/etc/config.xml +6 -1
- app/code/community/Demac/Optimal/sql/optimal_setup/install-0.3.5.php +18 -0
- app/code/community/Demac/Optimal/sql/optimal_setup/mysql4-install-0.3.5.php +18 -0
- app/code/community/Demac/Optimal/sql/optimal_setup/upgrade-0.3.4-0.3.5.php +21 -0
- app/design/adminhtml/default/default/template/optimal/info/creditcard.phtml +3 -0
- app/design/frontend/base/default/layout/optimal.xml +1 -1
- app/design/frontend/base/default/template/optimal/form/creditcard.phtml +16 -2
- app/design/frontend/base/default/template/optimal/info/creditcard.phtml +7 -0
- package.xml +14 -14
app/code/community/Demac/.DS_Store
ADDED
Binary file
|
app/code/community/Demac/Optimal/Block/Navigation.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Demac_Optimal_Block_Navigation extends Mage_Customer_Block_Account_Navigation
|
4 |
+
{
|
5 |
+
public function getLinks()
|
6 |
+
{
|
7 |
+
if (!Mage::helper('optimal')->canShow()) {
|
8 |
+
if (isset($this->_links['optimal_profiles'])) {
|
9 |
+
unset($this->_links['optimal_profiles']);
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
return parent::getLinks();
|
14 |
+
}
|
15 |
+
}
|
app/code/community/Demac/Optimal/Helper/Data.php
CHANGED
@@ -123,35 +123,65 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
|
|
123 |
|
124 |
$customerProfile['lastName'] = (string) $customerData['lastname'];
|
125 |
$customerProfile['firstName'] = (string) $customerData['firstname'];
|
|
|
|
|
|
|
|
|
126 |
|
127 |
if (!$customerData['is_guest']) {
|
128 |
-
|
129 |
-
if (!
|
130 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
if ($profile->getProfileId()) {
|
132 |
-
$customerProfile['id'] = (string)$profile->getProfileId();
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
}
|
141 |
-
} elseif($saveCard) {
|
142 |
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
$profile = Mage::getModel('optimal/creditcard')->loadByMerchantCustomerId($merchantCustomerId);
|
148 |
-
|
149 |
-
if($profile->getProfileId()) {
|
150 |
-
$customerProfile['id'] = (string)$profile->getProfileId();
|
151 |
-
}else {
|
152 |
-
$customerProfile['merchantCustomerId'] = $merchantCustomerId;
|
153 |
}
|
154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
}
|
156 |
}
|
157 |
|
@@ -178,7 +208,7 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
|
|
178 |
break;
|
179 |
}
|
180 |
|
181 |
-
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D');
|
182 |
|
183 |
if($skip3d)
|
184 |
{
|
@@ -186,11 +216,21 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
|
|
186 |
'key' => (string) 'skip3D',
|
187 |
'value' => true
|
188 |
);
|
|
|
|
|
|
|
|
|
|
|
189 |
} else {
|
190 |
$extendedOptionsArray[] = array(
|
191 |
'key' => (string) 'skip3D',
|
192 |
'value' => false
|
193 |
);
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
195 |
|
196 |
$addendumDataArray = array();
|
@@ -311,55 +351,37 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
|
|
311 |
'transaction.status'
|
312 |
),
|
313 |
'synchronous' => true,
|
314 |
-
'uri' => Mage::getBaseUrl()
|
315 |
);
|
316 |
|
317 |
// Callback information
|
318 |
$redirectArray = array();
|
|
|
|
|
319 |
$redirectArray[] = array(
|
320 |
'rel' => (string) 'on_success',
|
321 |
-
'returnKeys' =>
|
322 |
-
|
323 |
-
'transaction.confirmationNumber',
|
324 |
-
'transaction.status'
|
325 |
-
),
|
326 |
-
'uri' => Mage::getBaseUrl()
|
327 |
);
|
328 |
$redirectArray[] = array(
|
329 |
'rel' => (string) 'on_error',
|
330 |
-
'returnKeys' =>
|
331 |
-
|
332 |
-
'transaction.confirmationNumber',
|
333 |
-
'transaction.status'
|
334 |
-
),
|
335 |
-
'uri' => Mage::getBaseUrl()
|
336 |
);
|
337 |
$redirectArray[] = array(
|
338 |
'rel' => (string) 'on_decline',
|
339 |
-
'returnKeys' =>
|
340 |
-
|
341 |
-
'transaction.confirmationNumber',
|
342 |
-
'transaction.status'
|
343 |
-
),
|
344 |
-
'uri' => Mage::getBaseUrl()
|
345 |
);
|
346 |
$redirectArray[] = array(
|
347 |
'rel' => (string) 'on_timeout',
|
348 |
-
'returnKeys' =>
|
349 |
-
|
350 |
-
'transaction.confirmationNumber',
|
351 |
-
'transaction.status'
|
352 |
-
),
|
353 |
-
'uri' => Mage::getBaseUrl()
|
354 |
);
|
355 |
$redirectArray[] = array(
|
356 |
'rel' => (string) 'on_hold',
|
357 |
-
'returnKeys' =>
|
358 |
-
|
359 |
-
'transaction.confirmationNumber',
|
360 |
-
'transaction.status'
|
361 |
-
),
|
362 |
-
'uri' => Mage::getBaseUrl()
|
363 |
);
|
364 |
|
365 |
// Add extra information to the order Data
|
@@ -372,8 +394,8 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
|
|
372 |
$data['extendedOptions'] = $extendedOptionsArray;
|
373 |
$data['addendumData'] = $addendumDataArray;
|
374 |
|
|
|
375 |
return $data;
|
376 |
-
|
377 |
}
|
378 |
|
379 |
public function getMsgByCode($code = null)
|
@@ -393,4 +415,31 @@ class Demac_Optimal_Helper_Data extends Mage_Core_Helper_Abstract
|
|
393 |
return $msg;
|
394 |
}
|
395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
}
|
123 |
|
124 |
$customerProfile['lastName'] = (string) $customerData['lastname'];
|
125 |
$customerProfile['firstName'] = (string) $customerData['firstname'];
|
126 |
+
$merchantCustomerId = null;
|
127 |
+
|
128 |
+
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
|
129 |
+
$profilesEnabled = Mage::getStoreConfig('payment/optimal_profiles/active', Mage::app()->getStore()->getStoreId());
|
130 |
|
131 |
if (!$customerData['is_guest']) {
|
132 |
+
|
133 |
+
if (!isset($customerId)) {
|
134 |
+
$customerId = Mage::getSingleton('customer/session')->getId();
|
135 |
+
}
|
136 |
+
|
137 |
+
$profile = Mage::getModel('optimal/creditcard')->load($customerId, 'customer_id');
|
138 |
+
|
139 |
+
// If not skipping 3D and CreateProfiles is TRUE
|
140 |
+
if (!$skip3d && $profilesEnabled) {
|
141 |
+
|
142 |
if ($profile->getProfileId()) {
|
|
|
143 |
|
144 |
+
$customerProfile['id'] = (string) $profile->getProfileId();
|
145 |
+
|
146 |
+
} elseif (!isset($merchantCustomerId)) {
|
147 |
+
$merchantCustomerId = $this->getMerchantCustomerId($customerId);
|
148 |
+
$merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
|
149 |
+
$customerProfile['merchantCustomerId'] = $merchantCustomerId;
|
150 |
}
|
|
|
151 |
|
152 |
+
} elseif (!$skip3d && !$profilesEnabled) {
|
153 |
+
|
154 |
+
if ($profile->getProfileId()) {
|
155 |
+
$customerProfile['id'] = $profile->getProfileId();
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
}
|
157 |
|
158 |
+
} else {
|
159 |
+
if (!empty($customerData['profile_id'])) { // Check if there is a profile_id being passed
|
160 |
+
$profile = Mage::getModel('optimal/creditcard')->load((int)$customerData['profile_id']);
|
161 |
+
if ($profile->getProfileId()) {
|
162 |
+
$customerProfile['id'] = (string)$profile->getProfileId();
|
163 |
+
|
164 |
+
// In case the profile exists
|
165 |
+
if (!$saveCard) {
|
166 |
+
$customerProfile['paymentToken'] = (string)$profile->getPaymentToken();
|
167 |
+
}
|
168 |
+
} else {
|
169 |
+
Mage::throwException($this->__("The select profile does not exists."));
|
170 |
+
}
|
171 |
+
} elseif($saveCard) {
|
172 |
+
|
173 |
+
// Check for existing profile id
|
174 |
+
$customerId = Mage::getSingleton('customer/session')->getId();
|
175 |
+
$merchantCustomerId = $this->getMerchantCustomerId($customerId);
|
176 |
+
$merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
|
177 |
+
$profile = Mage::getModel('optimal/creditcard')->loadByMerchantCustomerId($merchantCustomerId);
|
178 |
+
|
179 |
+
if($profile->getProfileId()) {
|
180 |
+
$customerProfile['id'] = (string)$profile->getProfileId();
|
181 |
+
}else {
|
182 |
+
$customerProfile['merchantCustomerId'] = $merchantCustomerId;
|
183 |
+
}
|
184 |
+
}
|
185 |
}
|
186 |
}
|
187 |
|
208 |
break;
|
209 |
}
|
210 |
|
211 |
+
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
|
212 |
|
213 |
if($skip3d)
|
214 |
{
|
216 |
'key' => (string) 'skip3D',
|
217 |
'value' => true
|
218 |
);
|
219 |
+
// since we are skipping 3D-Secure check, hence we can process the order via Silent Post
|
220 |
+
$extendedOptionsArray[] = array(
|
221 |
+
'key' => 'silentPost',
|
222 |
+
'value' => true
|
223 |
+
);
|
224 |
} else {
|
225 |
$extendedOptionsArray[] = array(
|
226 |
'key' => (string) 'skip3D',
|
227 |
'value' => false
|
228 |
);
|
229 |
+
|
230 |
+
$extendedOptionsArray[] = array(
|
231 |
+
'key' => 'disablePaymentPageEditing',
|
232 |
+
'value' => true
|
233 |
+
);
|
234 |
}
|
235 |
|
236 |
$addendumDataArray = array();
|
351 |
'transaction.status'
|
352 |
),
|
353 |
'synchronous' => true,
|
354 |
+
'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
|
355 |
);
|
356 |
|
357 |
// Callback information
|
358 |
$redirectArray = array();
|
359 |
+
$returnKeys = array('id', 'transaction.confirmationNumber', 'transaction.status');
|
360 |
+
|
361 |
$redirectArray[] = array(
|
362 |
'rel' => (string) 'on_success',
|
363 |
+
'returnKeys' => $returnKeys,
|
364 |
+
'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
|
|
|
|
|
|
|
|
|
365 |
);
|
366 |
$redirectArray[] = array(
|
367 |
'rel' => (string) 'on_error',
|
368 |
+
'returnKeys' => $returnKeys,
|
369 |
+
'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
|
|
|
|
|
|
|
|
|
370 |
);
|
371 |
$redirectArray[] = array(
|
372 |
'rel' => (string) 'on_decline',
|
373 |
+
'returnKeys' => $returnKeys,
|
374 |
+
'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
|
|
|
|
|
|
|
|
|
375 |
);
|
376 |
$redirectArray[] = array(
|
377 |
'rel' => (string) 'on_timeout',
|
378 |
+
'returnKeys' => $returnKeys,
|
379 |
+
'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
|
|
|
|
|
|
|
|
|
380 |
);
|
381 |
$redirectArray[] = array(
|
382 |
'rel' => (string) 'on_hold',
|
383 |
+
'returnKeys' => $returnKeys,
|
384 |
+
'uri' => Mage::getBaseUrl() . 'optimal/handler/callback'
|
|
|
|
|
|
|
|
|
385 |
);
|
386 |
|
387 |
// Add extra information to the order Data
|
394 |
$data['extendedOptions'] = $extendedOptionsArray;
|
395 |
$data['addendumData'] = $addendumDataArray;
|
396 |
|
397 |
+
Mage::log($data, null, 'NetBanxData.log');
|
398 |
return $data;
|
|
|
399 |
}
|
400 |
|
401 |
public function getMsgByCode($code = null)
|
415 |
return $msg;
|
416 |
}
|
417 |
|
418 |
+
public function restoreQuote()
|
419 |
+
{
|
420 |
+
$checkoutSession = Mage::getSingleton('checkout/session');
|
421 |
+
$order = $checkoutSession->getLastRealOrder();
|
422 |
+
if ($order->getId()) {
|
423 |
+
$quote = Mage::getModel('sales/quote')->load($order->getQuoteId());
|
424 |
+
if ($quote->getId()) {
|
425 |
+
$quote->setIsActive(1)
|
426 |
+
->setReservedOrderId(null)
|
427 |
+
->save();
|
428 |
+
$checkoutSession->replaceQuote($quote)
|
429 |
+
->unsLastRealOrderId();
|
430 |
+
return true;
|
431 |
+
}
|
432 |
+
}
|
433 |
+
return false;
|
434 |
+
}
|
435 |
+
|
436 |
+
public function canShow()
|
437 |
+
{
|
438 |
+
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
|
439 |
+
$profilesEnabled = Mage::getStoreConfig('payment/optimal_profiles/active', Mage::app()->getStore()->getStoreId());
|
440 |
+
$show = ($profilesEnabled && $skip3d);
|
441 |
+
|
442 |
+
return $show;
|
443 |
+
}
|
444 |
+
|
445 |
}
|
app/code/community/Demac/Optimal/Model/Creditcard.php
CHANGED
@@ -27,4 +27,11 @@ class Demac_Optimal_Model_Creditcard extends Mage_Core_Model_Abstract
|
|
27 |
return $this;
|
28 |
|
29 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
}
|
27 |
return $this;
|
28 |
|
29 |
}
|
30 |
+
|
31 |
+
public function loadByCustomerId($customerId)
|
32 |
+
{
|
33 |
+
return $this->load($customerId, 'customer_id');
|
34 |
+
// $this->_getResource()->loadByCustomerId($this, $customerId);
|
35 |
+
// return $this;
|
36 |
+
}
|
37 |
}
|
app/code/community/Demac/Optimal/Model/Hosted/Client.php
CHANGED
@@ -199,30 +199,56 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
|
|
199 |
*/
|
200 |
protected function callApi($url, $method, $data = array())
|
201 |
{
|
202 |
-
|
|
|
203 |
$response = json_decode($this->_callApi($url,$method,$data));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
|
205 |
if (isset($response->error)) {
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
|
210 |
throw new Demac_Optimal_Model_Hosted_Exception($message);
|
211 |
-
return false;
|
212 |
}
|
213 |
|
214 |
if (isset($response->transaction->errorCode)) {
|
215 |
-
$message = $
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
|
218 |
-
$session = Mage::getSingleton('customer/session');
|
219 |
if (!$session->getCustomerId()) {
|
220 |
-
|
221 |
}
|
222 |
-
|
|
|
223 |
|
224 |
throw new Demac_Optimal_Model_Hosted_Exception($message);
|
225 |
-
return false;
|
226 |
}
|
227 |
|
228 |
return $response;
|
@@ -254,7 +280,6 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
|
|
254 |
*/
|
255 |
protected function _callApi($url,$mode,$data = array())
|
256 |
{
|
257 |
-
$helper = Mage::helper('optimal');
|
258 |
$data = json_encode($data);
|
259 |
|
260 |
try {
|
@@ -302,8 +327,8 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
|
|
302 |
Mage::logException($e);
|
303 |
return false;
|
304 |
}
|
305 |
-
Mage::log('OPTIMAL RESPONSE (_callApi):');
|
306 |
-
Mage::log($curl_response);
|
307 |
return $curl_response;
|
308 |
}
|
309 |
|
@@ -331,15 +356,20 @@ class Demac_Optimal_Model_Hosted_Client extends Demac_Optimal_Model_Client_Abstr
|
|
331 |
$this->_checkCurlVerifyPeer($curl);
|
332 |
|
333 |
//set the url, number of POST vars, POST data
|
334 |
-
curl_setopt($curl,CURLOPT_URL, $url);
|
335 |
-
curl_setopt($curl,CURLOPT_POST, true);
|
336 |
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
337 |
-
curl_setopt($curl,
|
|
|
338 |
$curl_response = curl_exec($curl);
|
339 |
|
340 |
-
|
341 |
-
|
|
|
|
|
|
|
342 |
curl_close($curl);
|
|
|
343 |
return true;
|
344 |
|
345 |
} catch (Exception $e) {
|
199 |
*/
|
200 |
protected function callApi($url, $method, $data = array())
|
201 |
{
|
202 |
+
$helper = Mage::helper('optimal');
|
203 |
+
$session = Mage::getSingleton('customer/session');
|
204 |
$response = json_decode($this->_callApi($url,$method,$data));
|
205 |
+
$defaultMessage = 'Payment Gateway Error. Please contact the site admin.';
|
206 |
+
|
207 |
+
if (isset($response->error) && !isset($response->error->code)) {
|
208 |
+
Mage::log('Corrupt Response from Gateway:', null, 'demac_optimal.log');
|
209 |
+
Mage::log($response, null, 'demac_optimal.log');
|
210 |
+
$helper->cleanMerchantCustomerId($session->getId());
|
211 |
+
throw new Demac_Optimal_Model_Hosted_Exception($defaultMessage);
|
212 |
+
}
|
213 |
|
214 |
if (isset($response->error)) {
|
215 |
+
$message = $helper->getMsgByCode($response->error->code);
|
216 |
+
|
217 |
+
if ($message === null && isset($response->error->message)) {
|
218 |
+
$message = $response->error->message;
|
219 |
+
} else {
|
220 |
+
$message = $defaultMessage;
|
221 |
+
}
|
222 |
+
|
223 |
+
$helper->cleanMerchantCustomerId($session->getId());
|
224 |
|
225 |
throw new Demac_Optimal_Model_Hosted_Exception($message);
|
|
|
226 |
}
|
227 |
|
228 |
if (isset($response->transaction->errorCode)) {
|
229 |
+
$message = $helper->getMsgByCode($response->transaction->errorCode);
|
230 |
+
|
231 |
+
if ($message === null && !isset($response->transaction->errorCode)) {
|
232 |
+
Mage::log('Corrupt Response from Gateway (transaction):', null, 'demac_optimal.log');
|
233 |
+
Mage::log($response, null, 'demac_optimal.log');
|
234 |
+
throw new Demac_Optimal_Model_Hosted_Exception($defaultMessage);
|
235 |
+
}
|
236 |
+
|
237 |
+
if ($message === null) {
|
238 |
+
$message = $response->transaction->errorMessage;
|
239 |
+
}
|
240 |
+
|
241 |
+
if (empty($message)) {
|
242 |
+
$message = $defaultMessage;
|
243 |
+
}
|
244 |
|
|
|
245 |
if (!$session->getCustomerId()) {
|
246 |
+
$session->addError($message);
|
247 |
}
|
248 |
+
|
249 |
+
Mage::helper('optimal')->cleanMerchantCustomerId($session->getId());
|
250 |
|
251 |
throw new Demac_Optimal_Model_Hosted_Exception($message);
|
|
|
252 |
}
|
253 |
|
254 |
return $response;
|
280 |
*/
|
281 |
protected function _callApi($url,$mode,$data = array())
|
282 |
{
|
|
|
283 |
$data = json_encode($data);
|
284 |
|
285 |
try {
|
327 |
Mage::logException($e);
|
328 |
return false;
|
329 |
}
|
330 |
+
Mage::log('OPTIMAL RESPONSE (_callApi):', null, 'demac_optimal.log');
|
331 |
+
Mage::log($curl_response, null, 'demac_optimal.log');
|
332 |
return $curl_response;
|
333 |
}
|
334 |
|
356 |
$this->_checkCurlVerifyPeer($curl);
|
357 |
|
358 |
//set the url, number of POST vars, POST data
|
359 |
+
curl_setopt($curl, CURLOPT_URL, $url);
|
360 |
+
curl_setopt($curl, CURLOPT_POST, true);
|
361 |
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
362 |
+
curl_setopt($curl, CURLOPT_HEADER, true);
|
363 |
+
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
|
364 |
$curl_response = curl_exec($curl);
|
365 |
|
366 |
+
$headers = substr($curl_response, 0, curl_getinfo($curl, CURLINFO_HEADER_SIZE));
|
367 |
+
$headers = explode("\n", $headers);
|
368 |
+
|
369 |
+
Mage::log('OPTIMAL RESPONSE (submitPayment):', null, 'demac_optimal.log');
|
370 |
+
Mage::log($curl_response, null, 'demac_optimal.log');
|
371 |
curl_close($curl);
|
372 |
+
|
373 |
return true;
|
374 |
|
375 |
} catch (Exception $e) {
|
app/code/community/Demac/Optimal/Model/Method/Hosted.php
CHANGED
@@ -145,6 +145,12 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
|
|
145 |
*/
|
146 |
public function validate()
|
147 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
$info = $this->getInfoInstance();
|
149 |
$errorMsg = false;
|
150 |
$availableTypes = explode(',',$this->getConfigData('cctypes'));
|
@@ -231,8 +237,17 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
|
|
231 |
$createProfile = $paymentData['optimal_create_profile'];
|
232 |
}
|
233 |
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
$customerData = $customer->getData();
|
237 |
$customerData['is_guest'] = false;
|
238 |
$customerData['lastname'] = (string)$customer->getLastname();
|
@@ -273,6 +288,43 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
|
|
273 |
Mage::throwException($this->__("There was a problem creating the order"));
|
274 |
}
|
275 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
|
277 |
if(isset($postURL)) {
|
278 |
$paymentData = $this->_preparePayment($payment->getData());
|
@@ -291,7 +343,7 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
|
|
291 |
|
292 |
if (!isset($orderStatus->transaction))
|
293 |
{
|
294 |
-
Mage::log('Transaction Object not present in orderStatus
|
295 |
Mage::throwException('Something went wrong with your transaction. Please contact support.');
|
296 |
}
|
297 |
|
@@ -300,69 +352,67 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
|
|
300 |
// Now we need to check the payment status if the transaction is available
|
301 |
if($transaction->status == 'declined' || $transaction->status == 'cancelled')
|
302 |
{
|
303 |
-
Mage::throwException($this->__("There was
|
304 |
-
}
|
305 |
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
}
|
317 |
-
|
318 |
-
// Set Profile Info
|
319 |
-
$profile->setCustomerId($order->getCustomerId());
|
320 |
-
$profile->setProfileId($orderStatus->profile->id);
|
321 |
-
$profile->setMerchantCustomerId($merchantCustomerId);
|
322 |
-
$profile->setPaymentToken($orderStatus->profile->paymentToken);
|
323 |
-
|
324 |
-
// Set Nickname
|
325 |
-
$cardName = $orderStatus->transaction->card->brand;
|
326 |
-
$profile->setCardNickname(Mage::helper('optimal')->processCardNickname($cardName));
|
327 |
-
|
328 |
-
// Set Nickname
|
329 |
-
//$cardHolder = $payment->getCcOwner();
|
330 |
-
$cardHolder = $customerData['firstname'] . ' ' . $customerData['lastname']; // $params['firstname'] . $params['lastname'];
|
331 |
-
$profile->setCardHolder($cardHolder);
|
332 |
-
|
333 |
-
// Set Card Info
|
334 |
-
$lastfour = $payment->getCcLast4();
|
335 |
-
$profile->setLastFourDigits($lastfour);
|
336 |
-
|
337 |
-
// Format card expiration date [todo]: Make a helper function
|
338 |
-
$expirationDate = sprintf("%02s", $paymentData['cardExpiryMonth']) . "/" . substr($paymentData['cardExpiryYear'], -2);
|
339 |
-
|
340 |
-
$profile->setCardExpiration($expirationDate);
|
341 |
-
|
342 |
-
$profile->save();
|
343 |
-
}else {
|
344 |
-
Mage::throwException($this->__("There was a problem saving your payment information."));
|
345 |
}
|
346 |
-
}
|
347 |
|
|
|
|
|
|
|
|
|
|
|
348 |
|
|
|
|
|
|
|
349 |
|
350 |
-
|
351 |
-
|
352 |
-
'
|
353 |
-
|
354 |
-
'Status: ' . $transaction->status .'<br/>'
|
355 |
-
);
|
356 |
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
|
|
364 |
|
|
|
|
|
|
|
|
|
365 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
}
|
367 |
|
368 |
return $this;
|
@@ -393,25 +443,28 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
|
|
393 |
|
394 |
return $fPaymentData;
|
395 |
}
|
396 |
-
|
|
|
|
|
|
|
|
|
397 |
protected function _getOptimalOrderStatus($client, $id, $counter = 0)
|
398 |
{
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
Mage::log('Get-Optimal-Order-Status Try #: ' . ($counter + 1));
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
Mage::throwException($e->getMessage());
|
409 |
-
return;
|
410 |
} catch(Exception $e) {
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
}
|
416 |
|
417 |
|
@@ -622,4 +675,55 @@ class Demac_Optimal_Model_Method_Hosted extends Mage_Payment_Model_Method_Cc
|
|
622 |
return $this;
|
623 |
}
|
624 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
625 |
}
|
145 |
*/
|
146 |
public function validate()
|
147 |
{
|
148 |
+
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
|
149 |
+
|
150 |
+
if (!$skip3d) {
|
151 |
+
return $this;
|
152 |
+
}
|
153 |
+
|
154 |
$info = $this->getInfoInstance();
|
155 |
$errorMsg = false;
|
156 |
$availableTypes = explode(',',$this->getConfigData('cctypes'));
|
237 |
$createProfile = $paymentData['optimal_create_profile'];
|
238 |
}
|
239 |
|
240 |
+
$checkoutMethod = Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod();
|
241 |
+
|
242 |
+
if ($checkoutMethod != 'guest') {
|
243 |
+
$quote = Mage::getSingleton('sales/quote')->load($order->getQuoteId());
|
244 |
+
$billing = $quote->getBillingAddress();
|
245 |
+
$customerData['is_guest'] = false;
|
246 |
+
$customerData['lastname'] = (string)$billing->getLastname();
|
247 |
+
$customerData['firstname'] = (string)$billing->getFirstname();
|
248 |
+
$customerData['email'] = (string)$billing->getEmail();
|
249 |
+
|
250 |
+
} elseif ($customerSession->isLoggedIn()){ // Get customer information
|
251 |
$customerData = $customer->getData();
|
252 |
$customerData['is_guest'] = false;
|
253 |
$customerData['lastname'] = (string)$customer->getLastname();
|
288 |
Mage::throwException($this->__("There was a problem creating the order"));
|
289 |
}
|
290 |
|
291 |
+
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D', Mage::app()->getStore()->getStoreId());
|
292 |
+
// Redirect the Customer if 3D-Secure verification is turned on
|
293 |
+
if (isset($postURL) && !$skip3d) {
|
294 |
+
|
295 |
+
try {
|
296 |
+
$order->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT);
|
297 |
+
$order->setStatus('pending_payment');
|
298 |
+
$order->addStatusHistoryComment('Redirecting the Customer to Optimal Payments for Payment Authorisation', 'pending_payment');
|
299 |
+
$order->addStatusHistoryComment(
|
300 |
+
'Netbanks Order Id: ' . $response->id .'<br/>' .
|
301 |
+
'Reference: # ' . $response->merchantRefNum .'<br/>'
|
302 |
+
);
|
303 |
+
$order->setIsNotified(false);
|
304 |
+
$order->save();
|
305 |
+
$checkoutSess = Mage::getSingleton('checkout/session');
|
306 |
+
$checkoutSess->unsQuoteId();
|
307 |
+
$checkoutSess->unsRedirectUrl();
|
308 |
+
|
309 |
+
$payment->setStatus('PENDING');
|
310 |
+
$payment->setAdditionalInformation('order', serialize(array('id' => $response->id)));
|
311 |
+
$payment->setTransactionId($response->id);
|
312 |
+
// magento will automatically close the transaction on auth preventing the invoice from being captured online.
|
313 |
+
$payment->setIsTransactionClosed(false);
|
314 |
+
$payment->save();
|
315 |
+
|
316 |
+
$this->orderRedirectUrl($postURL);
|
317 |
+
|
318 |
+
} catch (Exception $e) {
|
319 |
+
Mage::log($e->getMessage(), null, 'demac_optimal.log');
|
320 |
+
Mage::logException($e);
|
321 |
+
$checkoutSess->addError($this->__('An error was encountered while redirecting to the payment gateway, please try again later.'));
|
322 |
+
$this->_handlePaymentFailure();
|
323 |
+
$this->orderRedirectUrl(Mage::getBaseUrl() . 'checkout/cart');
|
324 |
+
}
|
325 |
+
|
326 |
+
return $this;
|
327 |
+
}
|
328 |
|
329 |
if(isset($postURL)) {
|
330 |
$paymentData = $this->_preparePayment($payment->getData());
|
343 |
|
344 |
if (!isset($orderStatus->transaction))
|
345 |
{
|
346 |
+
Mage::log('Aborting ... Transaction Object not present in orderStatus', null, 'demac_optimal.log');
|
347 |
Mage::throwException('Something went wrong with your transaction. Please contact support.');
|
348 |
}
|
349 |
|
352 |
// Now we need to check the payment status if the transaction is available
|
353 |
if($transaction->status == 'declined' || $transaction->status == 'cancelled')
|
354 |
{
|
355 |
+
Mage::throwException($this->__("There was an error processing your payment"));
|
356 |
+
}
|
357 |
|
358 |
+
// Check the order status for the profile information and try to save it
|
359 |
+
if($createProfile){
|
360 |
+
if(isset($orderStatus->profile)){
|
361 |
+
$profile = Mage::getModel('optimal/creditcard');
|
362 |
+
$merchantCustomerId = $orderStatus->profile->merchantCustomerId;
|
363 |
+
|
364 |
+
if(!isset($merchantCustomerId))
|
365 |
+
{
|
366 |
+
$merchantCustomerId = Mage::helper('optimal')->getMerchantCustomerId($order->getCustomerId());
|
367 |
+
$merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
}
|
|
|
369 |
|
370 |
+
// Set Profile Info
|
371 |
+
$profile->setCustomerId($order->getCustomerId());
|
372 |
+
$profile->setProfileId($orderStatus->profile->id);
|
373 |
+
$profile->setMerchantCustomerId($merchantCustomerId);
|
374 |
+
$profile->setPaymentToken($orderStatus->profile->paymentToken);
|
375 |
|
376 |
+
// Set Nickname
|
377 |
+
$cardName = $orderStatus->transaction->card->brand;
|
378 |
+
$profile->setCardNickname(Mage::helper('optimal')->processCardNickname($cardName));
|
379 |
|
380 |
+
// Set Nickname
|
381 |
+
//$cardHolder = $payment->getCcOwner();
|
382 |
+
$cardHolder = $customerData['firstname'] . ' ' . $customerData['lastname']; // $params['firstname'] . $params['lastname'];
|
383 |
+
$profile->setCardHolder($cardHolder);
|
|
|
|
|
384 |
|
385 |
+
// Set Card Info
|
386 |
+
$lastfour = $payment->getCcLast4();
|
387 |
+
$profile->setLastFourDigits($lastfour);
|
388 |
+
|
389 |
+
// Format card expiration date [todo]: Make a helper function
|
390 |
+
$expirationDate = sprintf("%02s", $paymentData['cardExpiryMonth']) . "/" . substr($paymentData['cardExpiryYear'], -2);
|
391 |
+
|
392 |
+
$profile->setCardExpiration($expirationDate);
|
393 |
|
394 |
+
$profile->save();
|
395 |
+
}else {
|
396 |
+
Mage::throwException($this->__("There was a problem saving your payment information."));
|
397 |
+
}
|
398 |
}
|
399 |
+
|
400 |
+
|
401 |
+
|
402 |
+
$order->addStatusHistoryComment(
|
403 |
+
'Netbanks Order Id: ' . $orderStatus->id .'<br/>' .
|
404 |
+
'Reference: # ' . $orderStatus->merchantRefNum .'<br/>' .
|
405 |
+
'Transaction Id: ' . $transaction->confirmationNumber .'<br/>' .
|
406 |
+
'Status: ' . $transaction->status .'<br/>'
|
407 |
+
);
|
408 |
+
|
409 |
+
$payment->setStatus('APPROVED');
|
410 |
+
$payment->setAdditionalInformation('order', serialize(array('id' => $orderStatus->id, 'optimal_profile_id' => $savedCreditCardProfileId)));
|
411 |
+
$payment->setAdditionalInformation('transaction', serialize($transaction));
|
412 |
+
$payment->setTransactionId($orderStatus->id);
|
413 |
+
// magento will automatically close the transaction on auth preventing the invoice from being captured online.
|
414 |
+
$payment->setIsTransactionClosed(false);
|
415 |
+
$payment->setAdditionalInformation('payment_type', $this->getInfoInstance()->getCcType());
|
416 |
}
|
417 |
|
418 |
return $this;
|
443 |
|
444 |
return $fPaymentData;
|
445 |
}
|
446 |
+
|
447 |
+
public function getOptimalOrderStatus($client, $id, $count = 0) {
|
448 |
+
return $this->_getOptimalOrderStatus($client, $id, $count);
|
449 |
+
}
|
450 |
+
|
451 |
protected function _getOptimalOrderStatus($client, $id, $counter = 0)
|
452 |
{
|
453 |
+
if($counter >= 3){
|
454 |
+
Mage::throwException('There was a problem retrieving the order information. Please contact support.');
|
455 |
+
}
|
456 |
+
|
457 |
+
Mage::log('Get-Optimal-Order-Status Try #: ' . ($counter + 1), null, 'demac_optimal.log');
|
458 |
+
|
459 |
+
try{
|
460 |
+
return $client->retrieveOrder($id);
|
461 |
+
} catch (Demac_Optimal_Model_Hosted_Exception $e) { // in case when Error is generated from Optimal
|
462 |
Mage::throwException($e->getMessage());
|
|
|
463 |
} catch(Exception $e) {
|
464 |
+
$counter++;
|
465 |
+
$this->_getOptimalOrderStatus($client, $id, $counter);
|
466 |
+
}
|
467 |
+
|
468 |
}
|
469 |
|
470 |
|
675 |
return $this;
|
676 |
}
|
677 |
|
678 |
+
public function orderRedirectUrl($url = null)
|
679 |
+
{
|
680 |
+
static $gatewayUrl;
|
681 |
+
|
682 |
+
if (!$url) {
|
683 |
+
return $gatewayUrl;
|
684 |
+
}
|
685 |
+
|
686 |
+
$gatewayUrl = $url;
|
687 |
+
|
688 |
+
return $gatewayUrl;
|
689 |
+
}
|
690 |
+
|
691 |
+
public function getOrderPlaceRedirectUrl()
|
692 |
+
{
|
693 |
+
return $this->orderRedirectUrl();
|
694 |
+
}
|
695 |
+
|
696 |
+
/**
|
697 |
+
* Handle Payment Failure
|
698 |
+
* - Cancel the order
|
699 |
+
* - Restore the quote
|
700 |
+
*
|
701 |
+
* Cancel Order and attempt to restore cart.
|
702 |
+
*
|
703 |
+
*/
|
704 |
+
protected function _handlePaymentFailure()
|
705 |
+
{
|
706 |
+
$session = Mage::getSingleton('checkout/session');
|
707 |
+
|
708 |
+
if ($session->getLastRealOrderId()) {
|
709 |
+
try {
|
710 |
+
$order = Mage::getModel('sales/order')->loadByIncrementId($session->getLastRealOrderId());
|
711 |
+
if ($order->getId()) {
|
712 |
+
$order->cancel()->save();
|
713 |
+
$quote = Mage::getModel('sales/quote')->load($order->getQuoteId());
|
714 |
+
if ($quote->getId()) {
|
715 |
+
$quote->setIsActive(1)
|
716 |
+
->setReservedOrderId(null)
|
717 |
+
->save();
|
718 |
+
|
719 |
+
$session->replaceQuote($quote)
|
720 |
+
->unsLastRealOrderId();
|
721 |
+
}
|
722 |
+
}
|
723 |
+
} catch (Exception $e) {
|
724 |
+
Mage::logException($e);
|
725 |
+
}
|
726 |
+
}
|
727 |
+
}
|
728 |
+
|
729 |
}
|
app/code/community/Demac/Optimal/Model/Observer.php
CHANGED
@@ -24,6 +24,7 @@ class Demac_Optimal_Model_Observer
|
|
24 |
|
25 |
if ($payment->getMethod() == 'optimal_hosted') {
|
26 |
$orderAdditionalInformation = $payment->getAdditionalInformation();
|
|
|
27 |
$transaction = unserialize($orderAdditionalInformation['transaction']);
|
28 |
|
29 |
if(!empty($transaction->riskReasonCode))
|
24 |
|
25 |
if ($payment->getMethod() == 'optimal_hosted') {
|
26 |
$orderAdditionalInformation = $payment->getAdditionalInformation();
|
27 |
+
|
28 |
$transaction = unserialize($orderAdditionalInformation['transaction']);
|
29 |
|
30 |
if(!empty($transaction->riskReasonCode))
|
app/code/community/Demac/Optimal/Test/Model/Hosted/Client.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Demac_Optimal_Test_Model_Hosted_Client extends EcomDev_PHPUnit_Test_Case
|
4 |
+
{
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Test that the payment method can authorize
|
9 |
+
*
|
10 |
+
* @test
|
11 |
+
*/
|
12 |
+
public function canAuthorize()
|
13 |
+
{
|
14 |
+
$this->assertEquals(true, false);
|
15 |
+
}
|
16 |
+
}
|
app/code/community/Demac/Optimal/Test/Model/Method/Hosted.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Demac_Optimal_Test_Model_Method_Hosted extends EcomDev_PHPUnit_Test_Case
|
4 |
+
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Test that the payment method can authorize
|
8 |
+
*
|
9 |
+
* @test
|
10 |
+
*/
|
11 |
+
public function canAuthorize()
|
12 |
+
{
|
13 |
+
$method = Mage::getModel('optimal/method_hosted');
|
14 |
+
|
15 |
+
$this->assertEquals(true, $method->canAuthorize());
|
16 |
+
}
|
17 |
+
}
|
app/code/community/Demac/Optimal/Test/Model/Observer.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Demac_Optimal_Test_Model_Observer extends EcomDev_PHPUnit_Test_Case
|
4 |
+
{
|
5 |
+
public function prepareOrderData()
|
6 |
+
{
|
7 |
+
|
8 |
+
}
|
9 |
+
}
|
app/code/community/Demac/Optimal/controllers/Frontend/OptimalController.php
CHANGED
@@ -190,6 +190,19 @@ class Demac_Optimal_Frontend_OptimalController extends Mage_Core_Controller_Fron
|
|
190 |
// Call the helper and get the data for netbanks
|
191 |
$data = $helper->prepareNetbanksOrderData($orderData ,$customerData, $createProfile, 'authorize');
|
192 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
// Call Netbanks API and create the order
|
194 |
$response = $client->createOrder($data);
|
195 |
if (isset($response->link)) {
|
@@ -213,6 +226,7 @@ class Demac_Optimal_Frontend_OptimalController extends Mage_Core_Controller_Fron
|
|
213 |
);
|
214 |
|
215 |
$paymentResponse = $client->submitPayment($postURL,$paymentData);
|
|
|
216 |
$orderStatus = $client->retrieveOrder($response->id);
|
217 |
$transaction = $orderStatus->transaction;
|
218 |
|
190 |
// Call the helper and get the data for netbanks
|
191 |
$data = $helper->prepareNetbanksOrderData($orderData ,$customerData, $createProfile, 'authorize');
|
192 |
|
193 |
+
foreach ($data['extendedOptions'] as $index => $xOp) {
|
194 |
+
if ($xOp['key'] == 'skip3D') {
|
195 |
+
$data['extendedOptions'][$index]['value'] = true;
|
196 |
+
}
|
197 |
+
}
|
198 |
+
|
199 |
+
// $data['extendedOptions'][] = array(
|
200 |
+
// 'key' => 'storeCardIndicator',
|
201 |
+
// 'value' => true
|
202 |
+
// );
|
203 |
+
|
204 |
+
Mage::log($data, null, 'optimal-addcc.log');
|
205 |
+
|
206 |
// Call Netbanks API and create the order
|
207 |
$response = $client->createOrder($data);
|
208 |
if (isset($response->link)) {
|
226 |
);
|
227 |
|
228 |
$paymentResponse = $client->submitPayment($postURL,$paymentData);
|
229 |
+
Mage::log($paymentResponse, null, 'optimnal-paymentrsp.log');
|
230 |
$orderStatus = $client->retrieveOrder($response->id);
|
231 |
$transaction = $orderStatus->transaction;
|
232 |
|
app/code/community/Demac/Optimal/controllers/HandlerController.php
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Demac_Optimal_HandlerController extends Mage_Core_Controller_Front_Action
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Callback Action
|
7 |
+
*
|
8 |
+
* Handle Success/Failure response from Payment Gateway
|
9 |
+
*/
|
10 |
+
public function callbackAction()
|
11 |
+
{
|
12 |
+
$params = $this->getRequest()->getParams();
|
13 |
+
$session = Mage::getSingleton('checkout/session');
|
14 |
+
|
15 |
+
$status = $params['transaction_status'];
|
16 |
+
$confirmation = $params['transaction_confirmationNumber'];
|
17 |
+
$optimalOrderId = $params['id'];
|
18 |
+
|
19 |
+
if ($status != 'success') {
|
20 |
+
$session->addError($this->__('Payment failed, please review your payment information and try again.'));
|
21 |
+
$this->_handlePaymentFailure();
|
22 |
+
$this->_redirect('checkout/cart');
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
try {
|
27 |
+
$this->_handlePaymentSuccess($session, $params);
|
28 |
+
} catch (Mage_Core_Exception $e) {
|
29 |
+
Mage::logException($e);
|
30 |
+
$this->_handlePaymentFailure();
|
31 |
+
$this->_redirect('checkout/onepage/failure');
|
32 |
+
}
|
33 |
+
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Handle Payment Failure
|
38 |
+
*
|
39 |
+
* Cancel Order and attempt to restore cart.
|
40 |
+
*
|
41 |
+
*/
|
42 |
+
protected function _handlePaymentFailure()
|
43 |
+
{
|
44 |
+
$session = Mage::getSingleton('checkout/session');
|
45 |
+
|
46 |
+
if ($session->getLastRealOrderId()) {
|
47 |
+
try {
|
48 |
+
$order = Mage::getModel('sales/order')->loadByIncrementId($session->getLastRealOrderId());
|
49 |
+
if ($order->getId()) {
|
50 |
+
$order->cancel()->save();
|
51 |
+
}
|
52 |
+
Mage::helper('optimal')->restoreQuote();
|
53 |
+
} catch (Exception $e) {
|
54 |
+
Mage::logException($e);
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Handle Payment Success
|
62 |
+
*
|
63 |
+
* Update Order status and create invoice
|
64 |
+
*
|
65 |
+
* @param $session
|
66 |
+
* @param $params
|
67 |
+
*/
|
68 |
+
protected function _handlePaymentSuccess($session, $params)
|
69 |
+
{
|
70 |
+
$status = $params['transaction_status'];
|
71 |
+
$confirmation = $params['transaction_confirmationNumber'];
|
72 |
+
$optimalOrderId = $params['id'];
|
73 |
+
|
74 |
+
$order = Mage::getModel('sales/order')->loadByIncrementId($session->getLastRealOrderId());
|
75 |
+
$payment = $order->getPayment();
|
76 |
+
|
77 |
+
// Now let's get the Order's status from Optimal
|
78 |
+
$client = Mage::getModel('optimal/hosted_client');
|
79 |
+
$orderStatus = Mage::getModel('optimal/method_hosted')->getOptimalOrderStatus($client, $optimalOrderId);
|
80 |
+
$transaction = $orderStatus->transaction;
|
81 |
+
|
82 |
+
$customerSession = Mage::getSingleton('customer/session');
|
83 |
+
list($month, $year) = explode('/', $transaction->card->expiry);
|
84 |
+
|
85 |
+
if ($customerSession->isLoggedIn()) {
|
86 |
+
$customerId = $customerSession->getId();
|
87 |
+
$customerData = Mage::getModel('customer/customer')->load($customerId)->getData();
|
88 |
+
$Card = Mage::getModel('optimal/creditcard');
|
89 |
+
$digits = $transaction->card->lastDigits;
|
90 |
+
|
91 |
+
$expiration = $month . '/' . substr($year, -2);
|
92 |
+
$profile = $Card->getCollection()
|
93 |
+
->addFieldToFilter('customer_id', $customerId)
|
94 |
+
->addFieldToFilter('last_four_digits', $digits)
|
95 |
+
->addFieldToFilter('card_expiration', $expiration)
|
96 |
+
->getFirstItem();
|
97 |
+
|
98 |
+
$merchantCustomerId = Mage::helper('optimal')->getMerchantCustomerId($customerId);
|
99 |
+
$merchantCustomerId = $merchantCustomerId['merchant_customer_id'];
|
100 |
+
|
101 |
+
// this means the CC is not saved
|
102 |
+
if (empty($profile)) {
|
103 |
+
$profile = Mage::getModel('optimal/creditcard');
|
104 |
+
}
|
105 |
+
|
106 |
+
// Set Profile Info
|
107 |
+
$profile->setCustomerId($customerId);
|
108 |
+
$profile->setProfileId($orderStatus->profile->id);
|
109 |
+
$profile->setMerchantCustomerId($merchantCustomerId);
|
110 |
+
$profile->setPaymentToken($orderStatus->profile->paymentToken);
|
111 |
+
|
112 |
+
// Set Nickname
|
113 |
+
$cardName = $orderStatus->transaction->card->brand;
|
114 |
+
$profile->setCardNickname(Mage::helper('optimal')->processCardNickname($cardName));
|
115 |
+
|
116 |
+
// Set Nickname
|
117 |
+
$cardHolder = $customerData['firstname'] . ' ' . $customerData['lastname']; // $params['firstname'] . $params['lastname'];
|
118 |
+
$profile->setCardHolder($cardHolder);
|
119 |
+
|
120 |
+
// Set Card Info
|
121 |
+
$profile->setLastFourDigits($transaction->card->lastDigits);
|
122 |
+
|
123 |
+
$profile->setCardExpiration($expiration);
|
124 |
+
|
125 |
+
$profile->save();
|
126 |
+
}
|
127 |
+
|
128 |
+
if (!isset($cardHolder)) {
|
129 |
+
$cardHolder = $orderStatus->profile->firstName . ' ' . $orderStatus->profile->lastName;
|
130 |
+
}
|
131 |
+
|
132 |
+
$order->addStatusHistoryComment(
|
133 |
+
'Netbanks Order Id: ' . $orderStatus->id .'<br/>' .
|
134 |
+
'Reference: # ' . $orderStatus->merchantRefNum .'<br/>' .
|
135 |
+
'Transaction Id: ' . $transaction->confirmationNumber .'<br/>' .
|
136 |
+
'Status: ' . $transaction->status .'<br/>'
|
137 |
+
);
|
138 |
+
|
139 |
+
$payment->setStatus('APPROVED');
|
140 |
+
$payment->setAdditionalInformation('order', serialize(array('id' => $optimalOrderId)));
|
141 |
+
$payment->setAdditionalInformation('transaction', serialize($transaction));
|
142 |
+
$payment->setTransactionId($optimalOrderId);
|
143 |
+
// magento will automatically close the transaction on auth preventing the invoice from being captured online.
|
144 |
+
$payment->setIsTransactionClosed(false);
|
145 |
+
$payment->setCcOwner($cardHolder)
|
146 |
+
->setCcType(Mage::helper('optimal')->processCardNickname($transaction->card->brand))
|
147 |
+
->setCcExpMonth($month)
|
148 |
+
->setCcExpYear($year)
|
149 |
+
->setCcLast4($transaction->card->lastDigits);
|
150 |
+
$payment->save();
|
151 |
+
|
152 |
+
$this->_redirect('checkout/onepage/success');
|
153 |
+
}
|
154 |
+
}
|
app/code/community/Demac/Optimal/etc/config.xml
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<config>
|
3 |
<modules>
|
4 |
<Demac_Optimal>
|
5 |
-
<version>0.3.
|
6 |
</Demac_Optimal>
|
7 |
</modules>
|
8 |
|
@@ -111,6 +111,11 @@
|
|
111 |
<optimal>
|
112 |
<class>Demac_Optimal_Block</class>
|
113 |
</optimal>
|
|
|
|
|
|
|
|
|
|
|
114 |
</blocks>
|
115 |
<helpers>
|
116 |
<optimal>
|
2 |
<config>
|
3 |
<modules>
|
4 |
<Demac_Optimal>
|
5 |
+
<version>0.3.9</version>
|
6 |
</Demac_Optimal>
|
7 |
</modules>
|
8 |
|
111 |
<optimal>
|
112 |
<class>Demac_Optimal_Block</class>
|
113 |
</optimal>
|
114 |
+
<customer>
|
115 |
+
<rewrite>
|
116 |
+
<account_navigation>Demac_Optimal_Block_Navigation</account_navigation>
|
117 |
+
</rewrite>
|
118 |
+
</customer>
|
119 |
</blocks>
|
120 |
<helpers>
|
121 |
<optimal>
|
app/code/community/Demac/Optimal/sql/optimal_setup/install-0.3.5.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$installer = $this;
|
3 |
+
|
4 |
+
$installer->startSetup();
|
5 |
+
|
6 |
+
$installer->run("
|
7 |
+
|
8 |
+
DROP TABLE IF EXISTS `{$this->getTable('optimal/errorcode')}`;
|
9 |
+
CREATE TABLE IF NOT EXISTS `{$this->getTable('optimal/errorcode')}` (
|
10 |
+
`code` varchar(5) NOT NULL,
|
11 |
+
`created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
12 |
+
`updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
13 |
+
PRIMARY KEY (`code`)
|
14 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
15 |
+
|
16 |
+
");
|
17 |
+
|
18 |
+
$installer->endSetup();
|
app/code/community/Demac/Optimal/sql/optimal_setup/mysql4-install-0.3.5.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$installer = $this;
|
3 |
+
|
4 |
+
$installer->startSetup();
|
5 |
+
|
6 |
+
$installer->run("
|
7 |
+
|
8 |
+
DROP TABLE IF EXISTS `{$this->getTable('optimal/errorcode')}`;
|
9 |
+
CREATE TABLE IF NOT EXISTS `{$this->getTable('optimal/errorcode')}` (
|
10 |
+
`code` varchar(5) NOT NULL,
|
11 |
+
`created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
12 |
+
`updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
13 |
+
PRIMARY KEY (`code`)
|
14 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
15 |
+
|
16 |
+
");
|
17 |
+
|
18 |
+
$installer->endSetup();
|
app/code/community/Demac/Optimal/sql/optimal_setup/upgrade-0.3.4-0.3.5.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$installer = $this;
|
3 |
+
|
4 |
+
$installer->startSetup();
|
5 |
+
|
6 |
+
$installer->run("
|
7 |
+
|
8 |
+
DROP TABLE IF EXISTS `{$this->getTable('optimal/errorcode')}`;
|
9 |
+
CREATE TABLE IF NOT EXISTS `{$this->getTable('optimal/errorcode')}` (
|
10 |
+
`code` varchar(50) NOT NULL,
|
11 |
+
`message` varchar(555) NOT NULL,
|
12 |
+
`custom_message` varchar(555) NULL,
|
13 |
+
`active` tinyint(1) NOT NULL DEFAULT '0',
|
14 |
+
`created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
15 |
+
`updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
16 |
+
PRIMARY KEY (`code`)
|
17 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
18 |
+
|
19 |
+
");
|
20 |
+
|
21 |
+
$installer->endSetup();
|
app/design/adminhtml/default/default/template/optimal/info/creditcard.phtml
CHANGED
@@ -1,5 +1,8 @@
|
|
1 |
<?php
|
2 |
$info = $this->getCardInfo();
|
|
|
|
|
|
|
3 |
?>
|
4 |
|
5 |
<?php if(isset($info)): ?>
|
1 |
<?php
|
2 |
$info = $this->getCardInfo();
|
3 |
+
if (!isset($info['name'])) {
|
4 |
+
$info['name'] = '';
|
5 |
+
}
|
6 |
?>
|
7 |
|
8 |
<?php if(isset($info)): ?>
|
app/design/frontend/base/default/layout/optimal.xml
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
-
<layout version="0.1.0">
|
3 |
<checkout_onepage_index translate="label" module="page">
|
4 |
<reference name="before_body_end">
|
5 |
<block type="optimal/threat" template="optimal/threatmeter.phtml" name="optimal_threat" as="optimal_threat"/>
|
1 |
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
<checkout_onepage_index translate="label" module="page">
|
4 |
<reference name="before_body_end">
|
5 |
<block type="optimal/threat" template="optimal/threatmeter.phtml" name="optimal_threat" as="optimal_threat"/>
|
app/design/frontend/base/default/template/optimal/form/creditcard.phtml
CHANGED
@@ -24,8 +24,16 @@
|
|
24 |
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
25 |
*/
|
26 |
?>
|
27 |
-
<?php
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
<div id="select_card_form" >
|
30 |
<ul class="profile_list form-list" id="payment_form_<?php echo $_code ?>" >
|
31 |
<li class="wide">
|
@@ -178,7 +186,13 @@
|
|
178 |
|
179 |
|
180 |
</script>
|
|
|
|
|
|
|
|
|
|
|
181 |
<?php else: ?>
|
|
|
182 |
<ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
|
183 |
<li>
|
184 |
<label for="<?php echo $_code ?>_cc_owner" class="required"><em>*</em><?php echo $this->__('Name on Card') ?></label>
|
24 |
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
25 |
*/
|
26 |
?>
|
27 |
+
<?php
|
28 |
+
$_code = $this->getMethodCode();
|
29 |
+
|
30 |
+
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D');
|
31 |
+
$profilesEnabled = ($this->hasOptimalProfiles() === true);
|
32 |
+
|
33 |
+
?>
|
34 |
+
|
35 |
+
|
36 |
+
<?php if($profilesEnabled && $skip3d): ?>
|
37 |
<div id="select_card_form" >
|
38 |
<ul class="profile_list form-list" id="payment_form_<?php echo $_code ?>" >
|
39 |
<li class="wide">
|
186 |
|
187 |
|
188 |
</script>
|
189 |
+
|
190 |
+
<?php elseif (!$skip3d): ?>
|
191 |
+
<ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
|
192 |
+
<li>You will be redirected to Optimal Payments for payment authorisation.</li>
|
193 |
+
</ul>
|
194 |
<?php else: ?>
|
195 |
+
|
196 |
<ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
|
197 |
<li>
|
198 |
<label for="<?php echo $_code ?>_cc_owner" class="required"><em>*</em><?php echo $this->__('Name on Card') ?></label>
|
app/design/frontend/base/default/template/optimal/info/creditcard.phtml
CHANGED
@@ -1,4 +1,11 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
$info = $this->getCardInfo();
|
3 |
?>
|
4 |
<?php echo $this->__('Credit Card Type: %s', $this->htmlEscape(ucwords($info['card_type']))) ?><br />
|
1 |
<?php
|
2 |
+
$skip3d = Mage::getStoreConfig('payment/optimal_hosted/skip3D');
|
3 |
+
// if 3D-Secure check is enabled, only show the Payment Method Title
|
4 |
+
if (!$skip3d) {
|
5 |
+
echo Mage::getStoreConfig('payment/optimal_hosted/title');
|
6 |
+
return;
|
7 |
+
}
|
8 |
+
|
9 |
$info = $this->getCardInfo();
|
10 |
?>
|
11 |
<?php echo $this->__('Credit Card Type: %s', $this->htmlEscape(ucwords($info['card_type']))) ?><br />
|
package.xml
CHANGED
@@ -1,24 +1,24 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>666999</name>
|
4 |
-
<version>0.3.
|
5 |
-
<stability>
|
6 |
-
<license
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>Securely access and process online payments with the NETBANX payment gateway.</summary>
|
10 |
-
<description>The Optimal Payments NETBANX Hosted Payment Extension allows ecommerce businesses to securely accept and process online payments using Optimal
|
11 |
-
&
|
12 |
-
The Optimal Payments extension uses a Silent Post integration to the merchant
|
13 |
-
&
|
14 |
-
This integration significantly reduces PCI compliance requirements and liability as all of the credit card information is processed in Optimal Payments Level 1 PCI compliant environment and servers leaving no sensitive customer payment information stored locally on merchant servers
|
15 |
-
&
|
16 |
Through the Optimal integration merchants also have the option to enable Threatmetrix fraud detection and management services. ThreatMetrix works by collecting relevant data about the customer and the order, and validating this information during the checkout. Fully integrated into the NETBANX payment gateway, enabling the ThreatMetrix option will allow merchants to automatically hold and flag suspicious orders, drastically reducing any fraud occurrences. Depending on the Score returned by ThreatMetrix an order can be held and flagged or altogether denied during the checkout.</description>
|
17 |
-
<notes>
|
18 |
<authors><author><name>Demac Media</name><user>demacmedia</user><email>support@demacmedia.com</email></author></authors>
|
19 |
-
<date>
|
20 |
-
<time>22:
|
21 |
-
<contents><target name="magecommunity"><dir name="Demac"><dir name="Optimal"><dir name="Block"><dir name="Adminhtml"><dir name="Errorcode"><dir name="Edit"><file name="Form.php" hash="56618ff0cc5f4c674f750412d0606aab"/></dir><file name="Edit.php" hash="8980988ca1324fac229b40f471d745c8"/><file name="Grid.php" hash="2d8ea2f836d380167e9b25a67acefd70"/></dir><file name="Errorcode.php" hash="9f0d3c6b0b51e3bedd239d3b727eff75"/><dir name="Risk"><dir name="Edit"><file name="Form.php" hash="25d4bcb59e33a94799bc9f6cb0509cc3"/><dir name="Tab"><file name="Form.php" hash="3731d284c28ed279eb5e00b41f494810"/></dir><file name="Tabs.php" hash="61a8d2ac9942356db313b423fc3c47c2"/></dir><file name="Edit.php" hash="959e8af1e6aae6d02560c98bcabea5ab"/><file name="Grid.php" hash="e999f01578aac6084520029f86852c09"/></dir><file name="Risk.php" hash="6bf5127ba14f9dd38519c6b62203f1f8"/></dir><dir name="Customer"><dir name="Cards"><file name="Form.php" hash="ce79e221d5caf995a10e47cbb4e51f8b"/><file name="Grid.php" hash="d14eb692082fe1299977e7b3ee75dcf3"/></dir><file name="Cards.php" hash="f99686c2296a850312713f6aadc4d04a"/></dir><dir name="Form"><file name="Creditcard.php" hash="d3642d432409cf55069253680bf9ee34"/></dir><dir name="Info"><file name="Creditcard.php" hash="7ba1df22bade177f4956ce9084fa98c6"/></dir><file name="Threat.php" hash="69605e0b8aacc80f47b5ed91e8631248"/></dir><dir name="Helper"><file name="Data.php" hash="
|
22 |
<compatible/>
|
23 |
-
<dependencies><required><php><min>5.3.0</min><max>5.
|
24 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>666999</name>
|
4 |
+
<version>0.3.9</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license>GPL</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>Securely access and process online payments with the NETBANX payment gateway.</summary>
|
10 |
+
<description>The Optimal Payments NETBANX Hosted Payment Extension allows ecommerce businesses to securely accept and process online payments using Optimal’s NETBANX payment gateway and services. The integration is easy to implement and provides the ultimate in payment processing capabilities, fraud management, and reporting.
|
11 |
+
<br /> <br />
|
12 |
+
The Optimal Payments extension uses a Silent Post integration to the merchant’s website. During checkout, payment information is entered on the merchant website and then transmitted securely via Silent Post for processing to the NETBANX payment gateway. The customer remains on the merchant’s website at all times allowing the merchant to manage the customer experience. When the customer clicks on the Pay button, payment data is transmitted directly to NETBANX using a PCI-compliant process without accessing any merchant servers.
|
13 |
+
<br /> <br />
|
14 |
+
This integration significantly reduces PCI compliance requirements and liability as all of the credit card information is processed in Optimal Payments Level 1 PCI compliant environment and servers leaving no sensitive customer payment information stored locally on merchant servers.
|
15 |
+
<br /> <br />
|
16 |
Through the Optimal integration merchants also have the option to enable Threatmetrix fraud detection and management services. ThreatMetrix works by collecting relevant data about the customer and the order, and validating this information during the checkout. Fully integrated into the NETBANX payment gateway, enabling the ThreatMetrix option will allow merchants to automatically hold and flag suspicious orders, drastically reducing any fraud occurrences. Depending on the Score returned by ThreatMetrix an order can be held and flagged or altogether denied during the checkout.</description>
|
17 |
+
<notes>Implements 3D Secure payment feature.</notes>
|
18 |
<authors><author><name>Demac Media</name><user>demacmedia</user><email>support@demacmedia.com</email></author></authors>
|
19 |
+
<date>2015-02-25</date>
|
20 |
+
<time>22:57:49</time>
|
21 |
+
<contents><target name="magecommunity"><dir name="Demac"><dir name="Optimal"><dir name="Block"><dir name="Adminhtml"><dir name="Errorcode"><dir name="Edit"><file name="Form.php" hash="56618ff0cc5f4c674f750412d0606aab"/></dir><file name="Edit.php" hash="8980988ca1324fac229b40f471d745c8"/><file name="Grid.php" hash="2d8ea2f836d380167e9b25a67acefd70"/></dir><file name="Errorcode.php" hash="9f0d3c6b0b51e3bedd239d3b727eff75"/><dir name="Risk"><dir name="Edit"><file name="Form.php" hash="25d4bcb59e33a94799bc9f6cb0509cc3"/><dir name="Tab"><file name="Form.php" hash="3731d284c28ed279eb5e00b41f494810"/></dir><file name="Tabs.php" hash="61a8d2ac9942356db313b423fc3c47c2"/></dir><file name="Edit.php" hash="959e8af1e6aae6d02560c98bcabea5ab"/><file name="Grid.php" hash="e999f01578aac6084520029f86852c09"/></dir><file name="Risk.php" hash="6bf5127ba14f9dd38519c6b62203f1f8"/></dir><dir name="Customer"><dir name="Cards"><file name="Form.php" hash="ce79e221d5caf995a10e47cbb4e51f8b"/><file name="Grid.php" hash="d14eb692082fe1299977e7b3ee75dcf3"/></dir><file name="Cards.php" hash="f99686c2296a850312713f6aadc4d04a"/></dir><dir name="Form"><file name="Creditcard.php" hash="d3642d432409cf55069253680bf9ee34"/></dir><dir name="Info"><file name="Creditcard.php" hash="7ba1df22bade177f4956ce9084fa98c6"/></dir><file name="Navigation.php" hash="d3b7d8765356b8da18d300cc9b1a447e"/><file name="Threat.php" hash="69605e0b8aacc80f47b5ed91e8631248"/></dir><dir name="Helper"><file name="Data.php" hash="69b5b351ee4685e4f51e0e3213ecb80e"/></dir><dir name="Model"><dir name="Client"><file name="Abstract.php" hash="f83275be8d3b248eb145d45c2a926d84"/></dir><dir name="Config"><file name="Mode.php" hash="798d2a9bab2c0fc2749116ac1a3fc926"/><file name="Status.php" hash="767ba25406456aae4a0bd86b11023b45"/><file name="Transaction.php" hash="e83e8427e4b14c4d3cd83058c68f8965"/></dir><dir name="Creditcard"><file name="Client.php" hash="f1014811d23c1cf5efbccf61c3c6c80c"/></dir><file name="Creditcard.php" hash="4754639f6fb3d4e1f1af0fd429e46092"/><file name="Errorcode.php" hash="dae5fa1abb705961bd9f15abf3d65ec0"/><dir name="Hosted"><file name="Client.php" hash="043fdac7d3c1c4af09424488d5d1cb7f"/><file name="Exception.php" hash="dfca385bc45b1c055bbf2e8e7031230b"/></dir><dir name="Merchant"><file name="Customer.php" hash="be743a5c7aababb9752bf961570b0c27"/></dir><dir name="Method"><file name="Hosted.php" hash="9f7da28c1cb5a0a508d33e91cebb81f7"/></dir><dir name="Mysql4"><dir name="Creditcard"><file name="Collection.php" hash="700985c287355082a3966d4b3f74838f"/></dir><file name="Creditcard.php" hash="a4e5ea4090d2f127edd19de9d2feb343"/><dir name="Errorcode"><file name="Collection.php" hash="075c7c98b606573f02aad1b096f13899"/></dir><file name="Errorcode.php" hash="0d19835b405402a5a5a7ae7c24a42c97"/><dir name="Merchant"><dir name="Customer"><file name="Collection.php" hash="aa0fbf9c0cc0a3207565443e35ae3779"/></dir><file name="Customer.php" hash="fe991d98537b7b3a07160d5b9b10802d"/></dir><dir name="Profile"><file name="Collection.php" hash="f5cd814fe62d2af8fbcc2214f94bfeb4"/></dir><file name="Profile.php" hash="6944c811248ef955a51357989ca11dd3"/><dir name="Risk"><file name="Collection.php" hash="558dc26690672dc09ae6fbfa8e780302"/></dir><file name="Risk.php" hash="5c77111382678451da4dde209a43b0fa"/></dir><file name="Observer.php" hash="cd89f8b6b1275718617c9841a5a1bbfa"/><dir name="Profile"><file name="Client.php" hash="4358736ced5bdc7d2a7fbbf53e2ff07d"/></dir><file name="Profile.php" hash="798cef09bbc0556545edf1f00bae9bf0"/><dir name="Resource"><dir name="Mysql4"><file name="Setup.php" hash="e936830d9e4f74badc3b7663f60436dc"/></dir></dir><file name="Risk.php" hash="fab5519b0e257b8ef2f66f5f76d49f2b"/><dir name="Sales"><file name="Order.php" hash="32320888ae209b1ea3208da59312da5c"/></dir><dir name="Source"><file name="Cctype.php" hash="dd21379a29444a4c58e33e90ddeb300e"/></dir><dir name="Web"><file name="Client.php" hash="d565e254fc281e7c246cc9cfe8c2f39d"/></dir></dir><dir name="Test"><dir name="Model"><dir name="Hosted"><file name="Client.php" hash="8aa8bb4bc740daa59be041827f7cf614"/></dir><dir name="Method"><file name="Hosted.php" hash="9d39c78d0617d136c66c4c52185706a7"/></dir><file name="Observer.php" hash="345883a098197f64e2063a97d17e6274"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="ErrorcodesController.php" hash="7149f83536e46413ddf5b159ae4ebf91"/><file name="ThreatController.php" hash="5db39713fbd0ae13e943a891940bb22c"/></dir><dir name="Frontend"><file name="OptimalController.php" hash="b67878eb0dd4310fbb6f84723cd6ce43"/></dir><file name="HandlerController.php" hash="b854169efa286fb13918bc2162ffc9e8"/></dir><dir name="data"><dir name="optimal_setup"><dir name="csv"><file name="common-codes-0.3.3.csv" hash="e3c9195dbe01cfb5cf341378271b1240"/><file name="webservices-codes-0.3.3.csv" hash="8fc5562ff9bb3e5c3235fa6c7c21c0d5"/></dir><file name="data-upgrade-0.3.4-0.3.5.php" hash="4afe267d997446c46c0a1fcba771d1e1"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="30a4af4a510783219bbee940d185fb19"/><file name="config.xml" hash="0b4d3d285ff172135da38f3c396d4d7f"/><file name="system.xml" hash="4e28392139fad2a08d168d0b1381f081"/></dir><dir name="sql"><dir name="optimal_setup"><file name="install-0.1.1.php" hash="422b6afb2d2320f5d9c59cd5bff0dc3d"/><file name="install-0.2.0.php" hash="71dbb515c55c34f1910463d72f66f9d2"/><file name="install-0.2.1.php" hash="0bd65edba72966cffce19dd3c480863b"/><file name="install-0.2.2.php" hash="33bb51df7561eb747ee07d8e8aa43ce4"/><file name="install-0.2.3.php" hash="abafde589308828b601c306b45f1aa41"/><file name="install-0.2.4.php" hash="abafde589308828b601c306b45f1aa41"/><file name="install-0.2.5.php" hash="9a0bb5235e982cfc1794dd8d0172e26d"/><file name="install-0.2.6.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.2.9.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="install-0.3.5.php" hash="1ed21269279cd8b0f6c20394a91c9d3b"/><file name="mysql4-install-0.1.1.php" hash="422b6afb2d2320f5d9c59cd5bff0dc3d"/><file name="mysql4-install-0.2.0.php" hash="71dbb515c55c34f1910463d72f66f9d2"/><file name="mysql4-install-0.2.1.php" hash="0bd65edba72966cffce19dd3c480863b"/><file name="mysql4-install-0.2.2.php" hash="33bb51df7561eb747ee07d8e8aa43ce4"/><file name="mysql4-install-0.2.3.php" hash="abafde589308828b601c306b45f1aa41"/><file name="mysql4-install-0.2.4.php" hash="abafde589308828b601c306b45f1aa41"/><file name="mysql4-install-0.2.5.php" hash="9a0bb5235e982cfc1794dd8d0172e26d"/><file name="mysql4-install-0.2.6.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.2.9.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="mysql4-install-0.3.5.php" hash="1ed21269279cd8b0f6c20394a91c9d3b"/><file name="mysql4-upgrade-0.1.1-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="upgrade-0.1.1-0.2.7.php" hash="0a8eb965fa5af575593d09722b6712b1"/><file name="upgrade-0.2.9-0.3.0.php" hash="989e6c4043fccfa6cdcba0a09938dd07"/><file name="upgrade-0.3.1-0.3.2.php" hash="aea721b40772c92db786b96fbb9c8bda"/><file name="upgrade-0.3.4-0.3.5.php" hash="5283e3567c7d35e22b4c87bbc89a0eb3"/><file name="upgrade-0.3.7-0.3.8.php" hash="5283e3567c7d35e22b4c87bbc89a0eb3"/></dir></dir></dir><file name=".DS_Store" hash="274a24b68e17a80774c8065fa0e5d839"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="optimal.xml" hash="03c64fd49785bfca34ee3249cc9bc97d"/></dir><dir name="template"><dir name="optimal"><dir name="customer"><dir name="cards"><file name="form.phtml" hash="969544827b5e5765b6bb2bea2f62392a"/><file name="grid.phtml" hash="9a160522aa31ed44eb2f5751f40718c8"/></dir><file name="cards.phtml" hash="ed3f6e56b134674e7d8ddcb6a1deac59"/></dir><dir name="form"><file name="creditcard.phtml" hash="38c3799facc887179afd3efbabf8ec93"/></dir><dir name="info"><file name="creditcard.phtml" hash="8ed46f25ea6bd04a67317743d8502e69"/></dir><file name="threatmeter.phtml" hash="3dd0ea7621038895aa1dd1e322ba7d99"/></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="optimal"><dir name="form"><file name="creditcard.phtml" hash="550c80a4e0dc4224946de029f4c3ecf6"/></dir><dir name="info"><file name="creditcard.phtml" hash="b40291e8e97dbcb6b7cf2f4b8ffb93f5"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Demac_Optimal.xml" hash="2ebfc5a3a1c5688639c0cc5eb34fded0"/></dir></target></contents>
|
22 |
<compatible/>
|
23 |
+
<dependencies><required><php><min>5.3.0</min><max>5.5.19</max></php></required></dependencies>
|
24 |
</package>
|