Signifyd_Connect - Version 3.6.0

Version Notes

Supports all versions of Magento

Download this release

Release Info

Developer Magento Core Team
Extension Signifyd_Connect
Version 3.6.0
Comparing to
See all releases


Code changes from version 3.5.3 to 3.6.0

app/code/community/Signifyd/Connect/Controllers/Adminhtml/SignifydController.php DELETED
@@ -1,21 +0,0 @@
1
- <?php
2
-
3
- class Signifyd_Connect_Adminhtml_SignifydController extends Mage_Adminhtml_Controller_Action
4
- {
5
- public function indexAction()
6
- {
7
- $this->_title($this->__('Sales'))->_title($this->__('Signifyd Scores'));
8
- $this->loadLayout();
9
- $this->_setActiveMenu('sales/sales');
10
- $this->_addContent($this->getLayout()->createBlock('signifyd_connect/adminhtml_sales_order'));
11
- $this->renderLayout();
12
- }
13
-
14
- public function gridAction()
15
- {
16
- $this->loadLayout();
17
- $this->getResponse()->setBody(
18
- $this->getLayout()->createBlock('signifyd_connect/adminhtml_sales_order_grid')->toHtml()
19
- );
20
- }
21
- }
app/code/community/Signifyd/Connect/Controllers/ConnectController.php DELETED
@@ -1,470 +0,0 @@
1
- <?php
2
-
3
- class Signifyd_Connect_ConnectController extends Mage_Core_Controller_Front_Action
4
- {
5
- public $_request = array();
6
- public $_topic = false;
7
- public $_order = false;
8
- public $_store_id = null;
9
- public $_case = false;
10
-
11
- public function getApiKey()
12
- {
13
- return Mage::getStoreConfig('signifyd_connect/settings/key');
14
- }
15
-
16
- public function holdThreshold()
17
- {
18
- return (int)Mage::getStoreConfig('signifyd_connect/advanced/hold_orders_threshold', $this->_store_id);
19
- }
20
-
21
- public function canHold()
22
- {
23
- return Mage::getStoreConfig('signifyd_connect/advanced/hold_orders', $this->_store_id);
24
- }
25
-
26
- public function canInvoice()
27
- {
28
- return Mage::getStoreConfig('signifyd_connect/advanced/invoice_orders', $this->_store_id);
29
- }
30
-
31
- public function notifyCustomer()
32
- {
33
- return Mage::getStoreConfig('signifyd_connect/advanced/invoice_orders_notify', $this->_store_id);
34
- }
35
-
36
- public function enabled()
37
- {
38
- $retrieve_scores = Mage::getStoreConfig('signifyd_connect/advanced/retrieve_score');
39
- $enabled = Mage::getStoreConfig('signifyd_connect/settings/enabled');
40
-
41
- return $enabled && $retrieve_scores;
42
- }
43
-
44
-
45
- public function getUrl($code)
46
- {
47
- return Mage::getStoreConfig('signifyd_connect/settings/url', $this->_store_id) . '/cases/' . $code;
48
- }
49
-
50
- public function logErrors()
51
- {
52
- return Mage::getStoreConfig('signifyd_connect/log/error');
53
- }
54
-
55
- public function logRequest()
56
- {
57
- return Mage::getStoreConfig('signifyd_connect/log/request');
58
- }
59
-
60
- public function getRawPost()
61
- {
62
- if (isset($HTTP_RAW_POST_DATA) && $HTTP_RAW_POST_DATA) {
63
- return $HTTP_RAW_POST_DATA;
64
- }
65
-
66
- $post = file_get_contents("php://input");
67
-
68
- if ($post) {
69
- return $post;
70
- }
71
-
72
- return '';
73
- }
74
-
75
- public function getDefaultMessage()
76
- {
77
- return 'This URL is working! Please copy & paste the current URL into your <a href="https://signifyd.com/settings">settings</a> page in the Notifications section';
78
- }
79
-
80
- public function getDisabledMessage()
81
- {
82
- return 'This URL is disabled in the Magento admin panel! Please enable score retrieval under Admin>System>Config>Signifyd Connect>Advanced before setting this url in your Signifyd <a href="https://signifyd.com/settings">settings</a> page.';
83
- }
84
-
85
- public function unsupported()
86
- {
87
- Mage::app()->getResponse()
88
- ->setHeader('HTTP/1.1','403 Forbidden')
89
- ->sendResponse();
90
- echo 'This request type is currently unsupported';
91
- exit;
92
- }
93
-
94
- public function complete()
95
- {
96
- Mage::app()->getResponse()
97
- ->setHeader('HTTP/1.1','200 Ok')
98
- ->sendResponse();
99
-
100
- exit;
101
- }
102
-
103
- public function validRequest($request, $hash)
104
- {
105
- $check = base64_encode(hash_hmac('sha256', $request, $this->getApiKey(), true));
106
-
107
- if ($this->logRequest()) {
108
- Mage::log('API request hash check: ' . $check, null, 'signifyd_connect.log');
109
- }
110
-
111
- if ($check == $hash) {
112
- return true;
113
- }
114
-
115
- return false;
116
- }
117
-
118
- public function initCase($order_increment)
119
- {
120
- $case = false;
121
-
122
- if (isset($this->_request['orderId'])) {
123
- $cases = Mage::getModel('signifyd_connect/case')->getCollection();
124
- $cases->addFieldToFilter('order_increment', $this->_request['orderId']);
125
-
126
- foreach ($cases as $c) {
127
- $case = $c;
128
- break;
129
- }
130
- }
131
-
132
- return $case;
133
- }
134
-
135
- public function initRequest($request)
136
- {
137
- $this->_request = json_decode($request, true);
138
-
139
- $topic = $this->getHeader('X-SIGNIFYD-TOPIC');
140
-
141
- $this->_topic = $topic;
142
-
143
- $this->_case = $this->initCase($this->_request['orderId']);
144
-
145
- $this->_order = Mage::getModel('sales/order')->loadByIncrementId($this->_request['orderId']);
146
-
147
- if ($this->_order && $this->_order->getId()) {
148
- $this->_store_id = $this->_order->getStoreId();
149
- }
150
-
151
- if (!$this->_case && $this->logRequest()) {
152
- Mage::log('No matching case was found for this request. order_increment: ' . $this->_request['orderId'], null, 'signifyd_connect.log');
153
- }
154
- }
155
-
156
- public function holdOrder($order)
157
- {
158
- if ($order && $order->getId() && $order->canHold() && $this->canHold()) {
159
- $order->hold();
160
- $order->save();
161
-
162
- if ($this->logRequest()) {
163
- Mage::log('Order ' . $order->getId() . ' held', null, 'signifyd_connect.log');
164
- }
165
- }
166
- }
167
-
168
- public function invoiceOrder($order)
169
- {
170
- if ($order && $order->getId() && $order->canInvoice() && $this->canInvoice()) {
171
- $items = array();
172
- foreach ($order->getAllItems() as $item) {
173
- $items[$item->getId()] = $item->getQtyOrdered();
174
- }
175
-
176
- $invoice_api = Mage::getModel('sales/order_invoice_api');
177
-
178
- try {
179
- $invoice_id = $invoice_api->create($order->getIncrementId(), $items, null, false, true);
180
-
181
- $invoice_api->capture($invoice_id);
182
- } catch (Exception $e) {
183
- if ($this->logErrors()) {
184
- Mage::log('Exception while creating invoice: ' . $e->__toString(), null, 'signifyd_connect.log');
185
- }
186
- }
187
- }
188
- }
189
-
190
- public function processAdditional($case, $original_status=false)
191
- {
192
- if ($this->canHold() || $this->canInvoice()) {
193
- $order = $this->_order;
194
- $held = false;
195
-
196
- if ($order && $order->getId() && $this->canHold()) {
197
- $threshold = $this->holdThreshold();
198
-
199
- if (!$original_status || $original_status == 'PENDING') {
200
- if ($threshold && $case->getScore() <= $threshold) {
201
- $this->holdOrder($order);
202
- $held = true;
203
- }
204
- } else if ($original_status) {
205
- if ($this->_request['reviewDisposition'] == 'FRAUDULENT') {
206
- if ($order->canHold()) {
207
- $order->hold();
208
- $order->save();
209
-
210
- if ($this->logRequest()) {
211
- Mage::log('Order ' . $order->getId() . ' held', null, 'signifyd_connect.log');
212
- }
213
- }
214
- } else if ($this->_request['reviewDisposition'] == 'GOOD') {
215
- if ($order->canUnhold()) {
216
- $order->unhold();
217
- $order->save();
218
-
219
- if ($this->logRequest()) {
220
- Mage::log('Order ' . $order->getId() . ' unheld', null, 'signifyd_connect.log');
221
- }
222
- }
223
- }
224
- }
225
- }
226
-
227
- if ($order && $order->getId() && $this->canInvoice() && !$held && !$original_status) {
228
- $this->invoiceOrder($order);
229
- }
230
- }
231
- }
232
-
233
- public function processCreation()
234
- {
235
- $case = $this->_case;
236
-
237
- if (!$case) {
238
- return;
239
- }
240
-
241
- if (isset($this->_request['score'])) {
242
- $case->setScore($this->_request['score']);
243
-
244
- if ($this->logRequest()) {
245
- Mage::log('Set score to ' . $this->_request['score'], null, 'signifyd_connect.log');
246
- }
247
- } else {
248
- if ($this->logRequest()) {
249
- Mage::log('No score value available', null, 'signifyd_connect.log');
250
- }
251
- }
252
-
253
- if (isset($this->_request['status'])) {
254
- $case->setSignifydStatus($this->_request['status']);
255
-
256
- if ($this->logRequest()) {
257
- Mage::log('Set status to ' . $this->_request['status'], null, 'signifyd_connect.log');
258
- }
259
- } else {
260
- if ($this->logRequest()) {
261
- Mage::log('No status value available', null, 'signifyd_connect.log');
262
- }
263
- }
264
-
265
- $case->setUpdated(strftime('%Y-%m-%d %H:%M:%S', time()));
266
- $case->save();
267
-
268
- if ($this->logRequest()) {
269
- Mage::log('Case ' . $case->getId() . ' created with status ' . $case->getSignifydStatus() . ' and score ' . $case->getScore(), null, 'signifyd_connect.log');
270
- }
271
-
272
- $this->processAdditional($case);
273
- }
274
-
275
- public function processReview()
276
- {
277
- $case = $this->_case;
278
-
279
- if (!$case) {
280
- return;
281
- }
282
-
283
- $original_status = $case->getSignifydStatus();
284
-
285
- if (isset($this->_request['score'])) {
286
- $case->setScore($this->_request['score']);
287
-
288
- if ($this->logRequest()) {
289
- Mage::log('Set score to ' . $this->_request['score'], null, 'signifyd_connect.log');
290
- }
291
- } else {
292
- if ($this->logRequest()) {
293
- Mage::log('No score value available', null, 'signifyd_connect.log');
294
- }
295
- }
296
-
297
- if (isset($this->_request['status'])) {
298
- $case->setSignifydStatus($this->_request['status']);
299
-
300
- if ($this->logRequest()) {
301
- Mage::log('Set status to ' . $this->_request['status'], null, 'signifyd_connect.log');
302
- }
303
- } else {
304
- if ($this->logRequest()) {
305
- Mage::log('No status value available', null, 'signifyd_connect.log');
306
- }
307
- }
308
-
309
- $case->setUpdated(strftime('%Y-%m-%d %H:%M:%S', time()));
310
- $case->save();
311
-
312
- $this->processAdditional($case, $original_status);
313
- }
314
-
315
- public function caseLookup()
316
- {
317
- $result = false;
318
- $case = $this->_case;
319
-
320
- try {
321
- $url = $this->getUrl($case->getCode());
322
-
323
- $response = Mage::helper('signifyd_connect')->request($url, null, $this->getApiKey(), null, 'application/json');
324
-
325
- $response_code = $response->getHttpCode();
326
-
327
- if (substr($response_code, 0, 1) == '2') {
328
- $result = json_decode($response->getRawResponse(), true);
329
- } else {
330
- if ($this->logRequest()) {
331
- Mage::log('Fallback request received a ' . $response_code . ' response from Signifyd', null, 'signifyd_connect.log');
332
- }
333
- }
334
- } catch (Exception $e) {
335
- if ($this->logErrors()) {
336
- Mage::log('Fallback issue: ' . $e->__toString(), null, 'signifyd_connect.log');
337
- }
338
- }
339
-
340
- return $result;
341
- }
342
-
343
- public function processFallback($request)
344
- {
345
- if ($this->logRequest()) {
346
- Mage::log('Attempting auth via fallback request', null, 'signifyd_connect.log');
347
- }
348
-
349
- $request = json_decode($request, true);
350
-
351
- $this->_topic = "cases/review"; // Topic header is most likely not available
352
-
353
- if (is_array($request) && isset($request['orderId'])) {
354
- $cases = Mage::getModel('signifyd_connect/case')->getCollection();
355
- $cases->addFieldToFilter('order_increment', $request['orderId']);
356
-
357
- foreach ($cases as $case) {
358
- $this->_case = $case;
359
- break;
360
- }
361
- }
362
-
363
- $this->_order = Mage::getModel('sales/order')->loadByIncrementId($this->_request['orderId']);
364
-
365
- if ($this->_order && $this->_order->getId()) {
366
- $this->_store_id = $this->_order->getStoreId();
367
- }
368
-
369
- if ($this->_case) {
370
- $lookup = $this->caseLookup();
371
-
372
- if ($lookup && is_array($lookup)) {
373
- $this->_request = $lookup;
374
-
375
- $this->processReview();
376
- } else {
377
- if ($this->logRequest()) {
378
- Mage::log('Fallback failed with an invalid response from Signifyd', null, 'signifyd_connect.log');
379
- }
380
- }
381
- } else {
382
- if ($this->logRequest()) {
383
- Mage::log('Fallback failed with no matching case found', null, 'signifyd_connect.log');
384
- }
385
- }
386
- }
387
-
388
- public function getHeader($header)
389
- {
390
- // T379: Some frameworks add an extra HTTP_ before the header, so check for both names
391
- // Header values stored in the $_SERVER variable have dashes converted to underscores, hence str_replace
392
- $direct = strtoupper(str_replace('-', '_', $header));
393
- $extraHttp = 'HTTP_' . $direct;
394
-
395
- // Check the $_SERVER global
396
- if (isset($_SERVER[$direct])) {
397
- return $_SERVER[$direct];
398
- } else if (isset($_SERVER[$extraHttp])) {
399
- return $_SERVER[$extraHttp];
400
- }
401
-
402
- Mage::log('Valid Header Not Found: ' . $header, null, 'signifyd_connect.log');
403
- return '';
404
-
405
- }
406
-
407
- public function apiAction()
408
- {
409
- if (!$this->enabled()) {
410
- echo $this->getDisabledMessage();
411
-
412
- return;
413
- }
414
-
415
- $request = $this->getRawPost();
416
-
417
- $hash = $this->getHeader('X-SIGNIFYD-SEC-HMAC-SHA256');
418
-
419
- if ($this->logRequest()) {
420
- Mage::log('API request: ' . $request, null, 'signifyd_connect.log');
421
- Mage::log('API request hash: ' . $hash, null, 'signifyd_connect.log');
422
- }
423
-
424
- if ($request) {
425
- if ($this->validRequest($request, $hash)) {
426
- $this->initRequest($request);
427
-
428
- $topic = $this->_topic;
429
-
430
- if ($this->logRequest()) {
431
- Mage::log('API request topic: ' . $topic, null, 'signifyd_connect.log');
432
- }
433
-
434
- switch ($topic) {
435
- case "cases/creation":
436
- try {
437
- $this->processCreation($request);
438
- } catch (Exception $e) {
439
- if ($this->logErrors()) {
440
- Mage::log('Case scoring issue: ' . $e->__toString(), null, 'signifyd_connect.log');
441
- }
442
- }
443
- break;
444
- case "cases/rescore":
445
- case "cases/review":
446
- try {
447
- $this->processReview($request);
448
- } catch (Exception $e) {
449
- if ($this->logErrors()) {
450
- Mage::log('Case review issue: ' . $e->__toString(), null, 'signifyd_connect.log');
451
- }
452
- }
453
- break;
454
- default:
455
- $this->unsupported();
456
- }
457
- } else {
458
- if ($this->logRequest()) {
459
- Mage::log('API request failed auth', null, 'signifyd_connect.log');
460
- }
461
-
462
- $this->processFallback($request);
463
- }
464
- } else {
465
- echo $this->getDefaultMessage();
466
- }
467
-
468
- $this->complete();
469
- }
470
- }
app/code/community/Signifyd/Connect/Model/Observer.php CHANGED
@@ -1,688 +1,694 @@
1
- <?php
2
-
3
- class Signifyd_Connect_Model_Observer extends Varien_Object
4
- {
5
- public $customer = null;
6
- public $order = null;
7
- public $payment = null;
8
- public $quote = null;
9
- public $shipping_address = null;
10
- public $billing_address = null;
11
-
12
- public $joins = 0;
13
-
14
- public function getProducts()
15
- {
16
- $products = array();
17
- $helper = Mage::helper('signifyd_connect');
18
-
19
- foreach ($this->quote->getAllItems() as $item) {
20
- if (!$item->getProductType() || $item->getProductType() == 'simple') {
21
- $product_object = $item->getData('product');
22
-
23
- if (!$product_object || !$product_object->getId()) {
24
- $product_object = Mage::getModel('catalog/product')->load($item->getProductId());
25
- }
26
-
27
- if ($product_object) {
28
- $product = array();
29
-
30
- $product['itemId'] = $item->getSku();
31
- $product['itemName'] = $item->getName();
32
- $product['itemUrl'] = $helper->getProductUrl($product_object);
33
- $product['itemImage'] = $helper->getProductImage($product_object);
34
-
35
- $qty = 1;
36
- if ($item->getQty()) {
37
- $qty = $item->getQty();
38
- } else if ($item->getQtyOrdered()) {
39
- $qty = $item->getQtyOrdered();
40
- }
41
-
42
- $price = 0;
43
- if ($item->getBasePrice() > 0) {
44
- $price = $item->getBasePrice();
45
- } else if ($item->getPrice() > 0) {
46
- $price = $item->getPrice();
47
- } else if ($product_object->getData('price') > 0) {
48
- $price = $product_object->getData('price');
49
- } else {
50
- $parent = $item->getData('parent');
51
-
52
- if (!$parent) {
53
- $parent = $item->getParentItem();
54
- }
55
-
56
- if ($parent) {
57
- if ($parent->getBasePrice() > 0) {
58
- $price = $parent->getBasePrice();
59
- } else if ($parent->getPrice()) {
60
- $price = $parent->getPrice();
61
- }
62
- }
63
- }
64
-
65
- $weight = 0;
66
- if ($item->hasWeight()) {
67
- $weight = $item->getWeight();
68
- } else if ($product_object->hasWeight()) {
69
- $weight = $product_object->getWeight();
70
- }
71
-
72
- $product['itemQuantity'] = intval($qty);
73
- $product['itemPrice'] = floatval($price);
74
- $product['itemWeight'] = floatval($weight);
75
-
76
- $products[] = $product;
77
- }
78
- }
79
- }
80
-
81
- return $products;
82
- }
83
-
84
- public function getIPAddress()
85
- {
86
- if ($this->order->getRemoteIp()) {
87
- if ($this->order->getXForwardedFor()) {
88
- return $this->filterIp($this->order->getXForwardedFor());
89
- }
90
-
91
- return $this->filterIp($this->order->getRemoteIp());
92
- }
93
-
94
- // Checks each configured value in app/etc/local.xml & falls back to REMOTE_ADDR. See app/etc/local.xml.additional for examples.
95
- return $this->filterIp(Mage::helper('core/http')->getRemoteAddr(false));
96
- }
97
-
98
- public function filterIp($ip)
99
- {
100
- $matches = array();
101
-
102
- if (preg_match('/[0-9]{1,3}(?:\.[0-9]{1,3}){3}/', $ip, $matches)) { //ipv4
103
- return current($matches);
104
- }
105
-
106
- if (preg_match('/[a-f0-9]{0,4}(?:\:[a-f0-9]{0,4}){2,7}/', strtolower($ip), $matches)) { //ipv6
107
- return current($matches);
108
- }
109
-
110
- return preg_replace('/[^0-9a-zA-Z:\.]/', '', strtok(str_replace($ip, ',', "\n"), "\n"));
111
- }
112
-
113
- public function formatAvs($value)
114
- {
115
- // http://www.emsecommerce.net/avs_cvv2_response_codes.htm
116
- $codes = array('X', 'Y', 'A', 'W', 'Z', 'N', 'U', 'R', 'E', 'S', 'D', 'M', 'B', 'P', 'C', 'I', 'G');
117
-
118
- if ($value) {
119
- $value = strtoupper($value);
120
-
121
- if (strlen($value) > 1) {
122
- if (preg_match('/\([A-Z]\)/', $value)) {
123
- $matches = array();
124
-
125
- preg_match('/\([A-Z]\)/', $value, $matches);
126
-
127
- foreach ($matches as $match) {
128
- $match = preg_replace('/[^A-Z]/', '', $match);
129
-
130
- if (in_array($match, $codes)) {
131
- $value = $match;
132
- }
133
- }
134
- }
135
- }
136
-
137
- if (strlen($value) > 1) {
138
- $value = substr($value, 0, 1);
139
- }
140
-
141
- if (!in_array($value, $codes)) {
142
- $value = null;
143
- }
144
- }
145
-
146
- return $value;
147
- }
148
-
149
- public function getAvsResponse()
150
- {
151
- $payment = $this->payment;
152
-
153
- $value = null;
154
-
155
- if ($payment->getAdditionalInformation('paypal_avs_code')) {
156
- $value = $payment->getAdditionalInformation('paypal_avs_code');
157
- } else if ($payment->getAdditionalInformation('cc_avs_status')) {
158
- $value = $payment->getAdditionalInformation('cc_avs_status');
159
- }
160
-
161
- return $this->formatAvs($value);
162
- }
163
-
164
- public function getCvvResponse()
165
- {
166
- $payment = $this->payment;
167
-
168
- if ($payment->getAdditionalInformation('paypal_cvv2_match')) {
169
- return $payment->getAdditionalInformation('paypal_cvv2_match');
170
- }
171
-
172
- return null;
173
- }
174
-
175
- public function getPaymentMethod()
176
- {
177
- return $this->payment->getMethod();
178
- }
179
-
180
- public function getPurchase()
181
- {
182
- $purchase = array();
183
-
184
- // T715: Send null rather than false when we can't get the IP Address
185
- $purchase['browserIpAddress'] = ($this->getIpAddress() ? $this->getIpAddress() : null);
186
- $purchase['orderId'] = $this->order->getIncrementId();
187
- $purchase['createdAt'] = date('c', strtotime($this->order->getCreatedAt())); // e.g: 2004-02-12T15:19:21+00:00
188
- $purchase['currency'] = $this->order->getBaseCurrencyCode();
189
- $purchase['totalPrice'] = floatval($this->order->getGrandTotal());
190
- $purchase['shippingPrice'] = floatval($this->order->getShippingAmount());
191
- $purchase['products'] = $this->getProducts();
192
- $purchase['paymentGateway'] = $this->getPaymentMethod();
193
-
194
- $purchase['avsResponseCode'] = $this->getAvsResponse();
195
- $purchase['cvvResponseCode'] = $this->getCvvResponse();
196
-
197
- return $purchase;
198
- }
199
-
200
- public function isPaymentCC($payment)
201
- {
202
- // Although the payment structure only has the entity data for the payment
203
- // the original payment method object is stored within the entity data.
204
- // It's not a requirement, but every CC handler I've found subclasses
205
- // from Mage_Payment_Model_Method_Cc, so we are using that as an
206
- // assumption for whether a method is based on CC data
207
- $method = $payment->getData('method_instance');
208
- if($method)
209
- {
210
- return is_subclass_of($method, 'Mage_Payment_Model_Method_Cc');
211
- }
212
- return false;
213
- }
214
-
215
- public function getCard()
216
- {
217
- $payment = $this->payment;
218
- $billing = $this->billing_address;
219
-
220
- $card = array();
221
-
222
- $card['cardHolderName'] = null;
223
- $card['bin'] = null;
224
- $card['last4'] = null;
225
- $card['expiryMonth'] = null;
226
- $card['expiryYear'] = null;
227
- $card['hash'] = null;
228
-
229
- $card['billingAddress'] = $this->getBillingAddress();
230
-
231
- if ($payment->getCcOwner()) {
232
- $card['cardHolderName'] = $payment->getCcOwner();
233
- } else {
234
- $card['cardHolderName'] = $billing->getFirstname() . ' ' . $billing->getLastname();
235
- }
236
-
237
- // Card data may be set on payment even if payment was not with card.
238
- // If it is, we want to ignore the data
239
- if(!$this->isPaymentCC($payment)) return $card;
240
-
241
- if ($payment->getData('cc_last4')) {
242
- $card['last4'] = $payment->getData('cc_last4');
243
- }
244
-
245
- if ($payment->getData('cc_exp_year')) {
246
- $card['expiryYear'] = $payment->getData('cc_exp_year');
247
- }
248
-
249
- if ($payment->getData('cc_exp_month')) {
250
- $card['expiryMonth'] = $payment->getData('cc_exp_month');
251
- }
252
-
253
- if ($payment->getData('cc_number_enc')) {
254
- $card['hash'] = $payment->getData('cc_number_enc');
255
- }
256
-
257
- if ($payment->getData('cc_number') && is_numeric($payment->getData('cc_number')) && strlen((string)$payment->getData('cc_number')) > 6) {
258
- $card['bin'] = substr((string)$payment->getData('cc_number'), 0, 6);
259
- }
260
-
261
- return $card;
262
- }
263
-
264
- public function getAddress($address_object)
265
- {
266
- $address = array();
267
-
268
- $address['streetAddress'] = $address_object->getStreet1();
269
- $address['unit'] = null;
270
-
271
- if ($address_object->getStreet2()) {
272
- $address['unit'] = $address_object->getStreet2();
273
- }
274
-
275
- $address['city'] = $address_object->getCity();
276
-
277
- $address['provinceCode'] = $address_object->getRegionCode();
278
- $address['postalCode'] = $address_object->getPostcode();
279
- $address['countryCode'] = $address_object->getCountryId();
280
-
281
- $address['latitude'] = null;
282
- $address['longitude'] = null;
283
-
284
- return $address;
285
- }
286
-
287
- public function getBillingAddress()
288
- {
289
- return $this->getAddress($this->billing_address);
290
- }
291
-
292
- public function getShippingAddress()
293
- {
294
- return $this->getAddress($this->shipping_address);
295
- }
296
-
297
- public function getRecipient()
298
- {
299
- $recipient = array();
300
-
301
- // In the case of non-shipped (ex: downloadable) orders, shipping address will be null so
302
- // in that case, we need to avoid the exception.
303
- if($this->shipping_address) {
304
- $recipient['deliveryAddress'] = $this->getShippingAddress();
305
- $recipient['fullName'] = $this->shipping_address->getFirstname() . ' ' . $this->shipping_address->getLastname();
306
- $recipient['confirmationPhone'] = $this->shipping_address->getTelephone();
307
- // Email: Note that this field is always the same for both addresses
308
- $recipient['confirmationEmail'] = $this->shipping_address->getEmail();
309
- }
310
- // Some customers have reported seeing "n/a@na.na" come through instead of a valid or null address
311
- // We suspect that it is due to an older version of Magento. If it becomes unnecessary, do remove the extra check.
312
- if (!$recipient['confirmationEmail'] || $recipient['confirmationEmail'] == 'n/a@na.na') {
313
- $recipient['confirmationEmail'] = $this->order->getCustomerEmail();
314
- }
315
-
316
-
317
- return $recipient;
318
- }
319
-
320
- public function getUserAccount()
321
- {
322
- $customer = $this->customer;
323
-
324
- $user = array(
325
- "emailAddress" => null,
326
- "username" => null,
327
- "phone" => null,
328
- "createdDate" => null,
329
- "accountNumber" => null,
330
- "lastOrderId" => null,
331
- "aggregateOrderCount" => null,
332
- "aggregateOrderDollars" => null,
333
- "lastUpdateDate" => null
334
- );
335
-
336
- if ($customer && $customer->getId()) {
337
- $user['emailAddress'] = $customer->getEmail();
338
-
339
- $user['phone'] = $this->billing_address->getTelephone();
340
-
341
- $user['createdDate'] = date('c', strtotime($customer->getCreatedAt()));
342
- $user['lastUpdateDate'] = date('c', strtotime($customer->getUpdatedAt()));
343
-
344
- $user['accountNumber'] = $customer->getId();
345
-
346
- $last_order_id = null;
347
-
348
- $orders = Mage::getModel('sales/order')->getCollection()->addFieldToFilter('customer_id', $customer->getId());
349
- $orders->getSelect()->order('created_at DESC');
350
-
351
- $aggregate_total = 0.;
352
- $order_count = 0;
353
-
354
- foreach ($orders as $order) {
355
- if ($last_order_id === null) {
356
- $last_order_id = $order->getIncrementId();
357
- }
358
-
359
- $aggregate_total += floatval($order->getGrandTotal());
360
- $order_count += 1;
361
- }
362
-
363
- $user['lastOrderId'] = $last_order_id;
364
- $user['aggregateOrderCount'] = $order_count;
365
- $user['aggregateOrderDollars'] = floatval($aggregate_total);
366
- }
367
-
368
- return $user;
369
- }
370
-
371
- public function getUrl()
372
- {
373
- if ($this->hasData('url')) {
374
- return $this->getData('url');
375
- }
376
-
377
- return Mage::getStoreConfig('signifyd_connect/settings/url') . '/cases';
378
- }
379
-
380
- public function getAuth()
381
- {
382
- if ($this->hasData('auth')) {
383
- return $this->getData('auth');
384
- }
385
-
386
- return Mage::getStoreConfig('signifyd_connect/settings/key');
387
- }
388
-
389
- public function submitCase($case)
390
- {
391
- $case = json_encode($case);
392
-
393
- return Mage::helper('signifyd_connect')->request($this->getUrl(), $case, $this->getAuth(), 'application/json');
394
- }
395
-
396
- public function generateCase()
397
- {
398
- $case = array();
399
-
400
- $case['purchase'] = $this->getPurchase();
401
- $case['recipient'] = $this->getRecipient();
402
- $case['card'] = $this->getCard();
403
- $case['userAccount'] = $this->getUserAccount();
404
-
405
- return $case;
406
- }
407
-
408
- public function getInvoiced($order)
409
- {
410
- $collection = $order->getInvoiceCollection();
411
-
412
- foreach ($collection as $invoice) {
413
- return true;
414
- }
415
-
416
- return false;
417
- }
418
-
419
- public function openCase($observer)
420
- {
421
- try {
422
- if (!Mage::getStoreConfig('signifyd_connect/settings/enabled') && !$this->getEnabled()) {
423
- return;
424
- }
425
-
426
- $event = $observer->getEvent();
427
-
428
- if ($event->hasOrder()) {
429
- $order = $event->getOrder();
430
- } else if ($event->hasObject()) {
431
- $order = $event->getObject();
432
- }
433
-
434
- $order_model = get_class(Mage::getModel('sales/order'));
435
-
436
- if (!($order instanceof $order_model)) {
437
- return;
438
- }
439
-
440
- if ($order && $order->getId()) {
441
- if (Mage::helper('signifyd_connect')->isProcessed($order) && !$this->getForceProcess()) {
442
- return;
443
- }
444
-
445
- $payments = $order->getPaymentsCollection();
446
-
447
- foreach ($payments as $payment) {
448
- $this->payment = $payment;
449
- }
450
-
451
- $method = $this->payment->getMethod();
452
-
453
- $state = $order->getState();
454
-
455
- if (!$state || $state == Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) {
456
- return;
457
- }
458
-
459
- $this->order = $order;
460
- $this->billing_address = $order->getBillingAddress();
461
- $this->shipping_address = $order->getShippingAddress();
462
-
463
- if ($order->getCustomer()) {
464
- $this->customer = $order->getCustomer();
465
- }
466
-
467
- $this->quote = $order->getQuote();
468
-
469
- if (!$this->quote) {
470
- $this->quote = $order;
471
- }
472
-
473
- $case = $this->generateCase();
474
-
475
- $case_object = Mage::helper('signifyd_connect')->markProcessed($order);
476
-
477
- $response = $this->submitCase($case);
478
-
479
- try {
480
- $response_code = $response->getHttpCode();
481
-
482
- if (substr($response_code, 0, 1) == '2') {
483
- $response_data = json_decode($response->getRawResponse(), true);
484
-
485
- $case_object = Mage::getModel('signifyd_connect/case')->load($case_object->getId());
486
- $case_object->setUpdated(strftime('%Y-%m-%d %H:%M:%S', time()));
487
- $case_object->setCode($response_data['investigationId']);
488
- $case_object->save();
489
- }
490
- } catch (Exception $e) {
491
-
492
- }
493
- }
494
- } catch (Exception $e) {
495
- Mage::log($e->__toString(), null, 'signifyd_connect.log');
496
- }
497
- }
498
-
499
- public function logData()
500
- {
501
- // Used to capture data for testing with
502
-
503
- $order_data = json_encode($this->order->getData());
504
- $billing_data = json_encode($this->order->getBillingAddress()->getData());
505
- $shipping_data = json_encode($this->order->getShippingAddress()->getData());
506
- $customer_data = json_encode($this->customer->getData());
507
- $payment_data = json_encode($this->payment->getData());
508
- $quote_data = json_encode($this->quote->getData());
509
- $items = array();
510
- $products = array();
511
-
512
- foreach ($this->quote->getAllItems() as $item) {
513
- $items[$item->getId()] = $item->getData();
514
- $product = Mage::getModel('catalog/product')->load($item->getProductId());
515
- $products[$item->getId()] = $product->getData();
516
- }
517
-
518
- $items = json_encode($items);
519
- $products = json_encode($products);
520
-
521
- Mage::log("Order:\n $order_data", null, 'signifyd_connect_objects.log');
522
- Mage::log("Billing:\n $billing_data", null, 'signifyd_connect_objects.log');
523
- Mage::log("Shipping:\n $shipping_data", null, 'signifyd_connect_objects.log');
524
- Mage::log("Customer:\n $customer_data", null, 'signifyd_connect_objects.log');
525
- Mage::log("Payment:\n $payment_data", null, 'signifyd_connect_objects.log');
526
- Mage::log("Quote:\n $quote_data", null, 'signifyd_connect_objects.log');
527
- Mage::log("Items:\n $items", null, 'signifyd_connect_objects.log');
528
- Mage::log("Products:\n $products", null, 'signifyd_connect_objects.log');
529
- }
530
-
531
- public function getAdminRoute()
532
- {
533
- $route = false;
534
-
535
- try {
536
- // 1.4.0.0 support means we need to hard code these paths
537
- if ((bool)(string)Mage::getConfig()->getNode('default/admin/url/use_custom_path')) {
538
- $route = Mage::getConfig()->getNode('default/admin/url/custom_path');
539
- } else {
540
- $route = Mage::getConfig()->getNode('admin/routers/adminhtml/args/frontName');
541
- }
542
- } catch (Exception $e) {
543
-
544
- }
545
-
546
- if (!$route) {
547
- $route = 'admin';
548
- }
549
-
550
- return $route;
551
- }
552
-
553
- public function eavCollectionAbstractLoadBefore($observer)
554
- {
555
- $x = $observer->getCollection();
556
-
557
- $request = Mage::app()->getRequest();
558
- $module = $request->getModuleName();
559
- $controller = $request->getControllerName();
560
- $action = $request->getActionName();
561
-
562
- if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
563
- return;
564
- }
565
-
566
- $clss = get_class($x);
567
- if ($clss == 'Mage_Sales_Model_Mysql4_Order_Collection' || $clss == 'Mage_Sales_Model_Mysql4_Order_Grid_Collection') {
568
- $observer->setOrderGridCollection($x);
569
- return $this->salesOrderGridCollectionLoadBefore($observer);
570
- }
571
- }
572
-
573
- public function coreCollectionAbstractLoadBefore($observer)
574
- {
575
- $x = $observer->getCollection();
576
-
577
- $request = Mage::app()->getRequest();
578
- $module = $request->getModuleName();
579
- $controller = $request->getControllerName();
580
- $action = $request->getActionName();
581
-
582
- if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
583
- return;
584
- }
585
-
586
- $clss = get_class($x);
587
-
588
- if ($clss == 'Mage_Sales_Model_Mysql4_Order_Collection' || $clss == 'Mage_Sales_Model_Mysql4_Order_Grid_Collection') {
589
- $observer->setOrderGridCollection($x);
590
- return $this->salesOrderGridCollectionLoadBefore($observer);
591
- }
592
- }
593
-
594
- public function isCe()
595
- {
596
- return !@class_exists('Enterprise_Cms_Helper_Data');
597
- }
598
-
599
- public function oldSupport()
600
- {
601
- $version = Mage::getVersion();
602
-
603
- if ($this->isCe()) {
604
- return version_compare($version, '1.4.1.0', '<');
605
- } else {
606
- return version_compare($version, '1.10.0.0', '<');
607
- }
608
-
609
- return false;
610
- }
611
-
612
- public function belowSix()
613
- {
614
- $version = Mage::getVersion();
615
-
616
- if ($this->isCe()) {
617
- return version_compare($version, '1.6.0.0', '<');
618
- } else {
619
- return version_compare($version, '1.11.0.0', '<');
620
- }
621
-
622
- return false;
623
- }
624
-
625
- public function salesOrderGridCollectionLoadBefore($observer)
626
- {
627
- if ($this->joins === 0) {
628
- $request = Mage::app()->getRequest();
629
- $module = $request->getModuleName();
630
- $controller = $request->getControllerName();
631
- $action = $request->getActionName();
632
-
633
- if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
634
- return;
635
- }
636
-
637
- $collection = $observer->getOrderGridCollection();
638
- $select = $collection->getSelect();
639
-
640
- if (Mage::getStoreConfig('signifyd_connect/advanced/show_scores')) {
641
- if ($this->oldSupport()) {
642
- $select->joinLeft(array('signifyd'=>$collection->getTable('signifyd_connect/case')), 'signifyd.order_increment=e.increment_id', array('score'=>'score'));
643
- $this->joins++;
644
- } else {
645
- $select->joinLeft(array('signifyd'=>$collection->getTable('signifyd_connect/case')), 'signifyd.order_increment=main_table.increment_id', array('score'=>'score'));
646
- $this->joins++;
647
- }
648
-
649
- Mage::log('joined');
650
- }
651
- }
652
- }
653
-
654
- public function coreBlockAbstractToHtmlBefore(Varien_Event_Observer $observer)
655
- {
656
- if (Mage::getStoreConfig('signifyd_connect/advanced/show_scores')) {
657
- $request = Mage::app()->getRequest();
658
- $module = $request->getModuleName();
659
- $controller = $request->getControllerName();
660
- $action = $request->getActionName();
661
-
662
- if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
663
- return;
664
- }
665
-
666
- $helper = Mage::helper('signifyd_connect');
667
- $block = $observer->getEvent()->getBlock();
668
-
669
- if ($block->getId() == 'sales_order_grid') {
670
- $block->addColumnAfter(
671
- 'score',
672
- array(
673
- 'header' => $helper->__('Signifyd Score'),
674
- 'align' => 'left',
675
- 'type' => 'text',
676
- 'index' => 'score',
677
- 'filter' => false,
678
- 'renderer' => 'signifyd_connect/renderer',
679
- 'width' => '100px',
680
- ),
681
- 'status'
682
- );
683
-
684
- $block->sortColumnsByOrder();
685
- }
686
- }
687
- }
688
- }
1
+ <?php
2
+
3
+ class Signifyd_Connect_Model_Observer extends Varien_Object
4
+ {
5
+ public $customer = null;
6
+ public $order = null;
7
+ public $payment = null;
8
+ public $quote = null;
9
+ public $shipping_address = null;
10
+ public $billing_address = null;
11
+
12
+ public $joins = 0;
13
+
14
+ public function getProducts()
15
+ {
16
+ $products = array();
17
+ $helper = Mage::helper('signifyd_connect');
18
+
19
+ foreach ($this->quote->getAllItems() as $item) {
20
+ if (!$item->getProductType() || $item->getProductType() == 'simple') {
21
+ $product_object = $item->getData('product');
22
+
23
+ if (!$product_object || !$product_object->getId()) {
24
+ $product_object = Mage::getModel('catalog/product')->load($item->getProductId());
25
+ }
26
+
27
+ if ($product_object) {
28
+ $product = array();
29
+
30
+ $product['itemId'] = $item->getSku();
31
+ $product['itemName'] = $item->getName();
32
+ $product['itemUrl'] = $helper->getProductUrl($product_object);
33
+ $product['itemImage'] = $helper->getProductImage($product_object);
34
+
35
+ $qty = 1;
36
+ if ($item->getQty()) {
37
+ $qty = $item->getQty();
38
+ } else if ($item->getQtyOrdered()) {
39
+ $qty = $item->getQtyOrdered();
40
+ }
41
+
42
+ $price = 0;
43
+ if ($item->getBasePrice() > 0) {
44
+ $price = $item->getBasePrice();
45
+ } else if ($item->getPrice() > 0) {
46
+ $price = $item->getPrice();
47
+ } else if ($product_object->getData('price') > 0) {
48
+ $price = $product_object->getData('price');
49
+ } else {
50
+ $parent = $item->getData('parent');
51
+
52
+ if (!$parent) {
53
+ $parent = $item->getParentItem();
54
+ }
55
+
56
+ if ($parent) {
57
+ if ($parent->getBasePrice() > 0) {
58
+ $price = $parent->getBasePrice();
59
+ } else if ($parent->getPrice()) {
60
+ $price = $parent->getPrice();
61
+ }
62
+ }
63
+ }
64
+
65
+ $weight = 0;
66
+ if ($item->hasWeight()) {
67
+ $weight = $item->getWeight();
68
+ } else if ($product_object->hasWeight()) {
69
+ $weight = $product_object->getWeight();
70
+ }
71
+
72
+ $product['itemQuantity'] = intval($qty);
73
+ $product['itemPrice'] = floatval($price);
74
+ $product['itemWeight'] = floatval($weight);
75
+
76
+ $products[] = $product;
77
+ }
78
+ }
79
+ }
80
+
81
+ return $products;
82
+ }
83
+
84
+ public function getIPAddress()
85
+ {
86
+ if ($this->order->getRemoteIp()) {
87
+ if ($this->order->getXForwardedFor()) {
88
+ return $this->filterIp($this->order->getXForwardedFor());
89
+ }
90
+
91
+ return $this->filterIp($this->order->getRemoteIp());
92
+ }
93
+
94
+ // Checks each configured value in app/etc/local.xml & falls back to REMOTE_ADDR. See app/etc/local.xml.additional for examples.
95
+ return $this->filterIp(Mage::helper('core/http')->getRemoteAddr(false));
96
+ }
97
+
98
+ public function filterIp($ip)
99
+ {
100
+ $matches = array();
101
+
102
+ if (preg_match('/[0-9]{1,3}(?:\.[0-9]{1,3}){3}/', $ip, $matches)) { //ipv4
103
+ return current($matches);
104
+ }
105
+
106
+ if (preg_match('/[a-f0-9]{0,4}(?:\:[a-f0-9]{0,4}){2,7}/', strtolower($ip), $matches)) { //ipv6
107
+ return current($matches);
108
+ }
109
+
110
+ return preg_replace('/[^0-9a-zA-Z:\.]/', '', strtok(str_replace($ip, ',', "\n"), "\n"));
111
+ }
112
+
113
+ public function formatAvs($value)
114
+ {
115
+ // http://www.emsecommerce.net/avs_cvv2_response_codes.htm
116
+ $codes = array('X', 'Y', 'A', 'W', 'Z', 'N', 'U', 'R', 'E', 'S', 'D', 'M', 'B', 'P', 'C', 'I', 'G');
117
+
118
+ if ($value) {
119
+ $value = strtoupper($value);
120
+
121
+ if (strlen($value) > 1) {
122
+ if (preg_match('/\([A-Z]\)/', $value)) {
123
+ $matches = array();
124
+
125
+ preg_match('/\([A-Z]\)/', $value, $matches);
126
+
127
+ foreach ($matches as $match) {
128
+ $match = preg_replace('/[^A-Z]/', '', $match);
129
+
130
+ if (in_array($match, $codes)) {
131
+ $value = $match;
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ if (strlen($value) > 1) {
138
+ $value = substr($value, 0, 1);
139
+ }
140
+
141
+ if (!in_array($value, $codes)) {
142
+ $value = null;
143
+ }
144
+ }
145
+
146
+ return $value;
147
+ }
148
+
149
+ public function getAvsResponse()
150
+ {
151
+ $payment = $this->payment;
152
+
153
+ $value = null;
154
+
155
+ if ($payment->getAdditionalInformation('paypal_avs_code')) {
156
+ $value = $payment->getAdditionalInformation('paypal_avs_code');
157
+ } else if ($payment->getAdditionalInformation('cc_avs_status')) {
158
+ $value = $payment->getAdditionalInformation('cc_avs_status');
159
+ }
160
+
161
+ return $this->formatAvs($value);
162
+ }
163
+
164
+ public function getCvvResponse()
165
+ {
166
+ $payment = $this->payment;
167
+
168
+ if ($payment->getAdditionalInformation('paypal_cvv2_match')) {
169
+ return $payment->getAdditionalInformation('paypal_cvv2_match');
170
+ }
171
+
172
+ return null;
173
+ }
174
+
175
+ public function getPaymentMethod()
176
+ {
177
+ return $this->payment->getMethod();
178
+ }
179
+
180
+ private function getTransactionId()
181
+ {
182
+ return $this->payment->getTransactionId();
183
+ }
184
+
185
+ public function getPurchase()
186
+ {
187
+ $purchase = array();
188
+
189
+ // T715: Send null rather than false when we can't get the IP Address
190
+ $purchase['browserIpAddress'] = ($this->getIpAddress() ? $this->getIpAddress() : null);
191
+ $purchase['orderId'] = $this->order->getIncrementId();
192
+ $purchase['createdAt'] = date('c', strtotime($this->order->getCreatedAt())); // e.g: 2004-02-12T15:19:21+00:00
193
+ $purchase['currency'] = $this->order->getBaseCurrencyCode();
194
+ $purchase['totalPrice'] = floatval($this->order->getGrandTotal());
195
+ $purchase['shippingPrice'] = floatval($this->order->getShippingAmount());
196
+ $purchase['products'] = $this->getProducts();
197
+ $purchase['paymentGateway'] = $this->getPaymentMethod();
198
+ $purchase['transactionId'] = $this->getTransactionId();
199
+
200
+ $purchase['avsResponseCode'] = $this->getAvsResponse();
201
+ $purchase['cvvResponseCode'] = $this->getCvvResponse();
202
+
203
+ return $purchase;
204
+ }
205
+
206
+ public function isPaymentCC($payment)
207
+ {
208
+ // Although the payment structure only has the entity data for the payment
209
+ // the original payment method object is stored within the entity data.
210
+ // It's not a requirement, but every CC handler I've found subclasses
211
+ // from Mage_Payment_Model_Method_Cc, so we are using that as an
212
+ // assumption for whether a method is based on CC data
213
+ $method = $payment->getData('method_instance');
214
+ if($method)
215
+ {
216
+ return is_subclass_of($method, 'Mage_Payment_Model_Method_Cc');
217
+ }
218
+ return false;
219
+ }
220
+
221
+ public function getCard()
222
+ {
223
+ $payment = $this->payment;
224
+ $billing = $this->billing_address;
225
+
226
+ $card = array();
227
+
228
+ $card['cardHolderName'] = null;
229
+ $card['bin'] = null;
230
+ $card['last4'] = null;
231
+ $card['expiryMonth'] = null;
232
+ $card['expiryYear'] = null;
233
+ $card['hash'] = null;
234
+
235
+ $card['billingAddress'] = $this->getBillingAddress();
236
+
237
+ if ($payment->getCcOwner()) {
238
+ $card['cardHolderName'] = $payment->getCcOwner();
239
+ } else {
240
+ $card['cardHolderName'] = $billing->getFirstname() . ' ' . $billing->getLastname();
241
+ }
242
+
243
+ // Card data may be set on payment even if payment was not with card.
244
+ // If it is, we want to ignore the data
245
+ if(!$this->isPaymentCC($payment)) return $card;
246
+
247
+ if ($payment->getData('cc_last4')) {
248
+ $card['last4'] = $payment->getData('cc_last4');
249
+ }
250
+
251
+ if ($payment->getData('cc_exp_year')) {
252
+ $card['expiryYear'] = $payment->getData('cc_exp_year');
253
+ }
254
+
255
+ if ($payment->getData('cc_exp_month')) {
256
+ $card['expiryMonth'] = $payment->getData('cc_exp_month');
257
+ }
258
+
259
+ if ($payment->getData('cc_number_enc')) {
260
+ $card['hash'] = $payment->getData('cc_number_enc');
261
+ }
262
+
263
+ if ($payment->getData('cc_number') && is_numeric($payment->getData('cc_number')) && strlen((string)$payment->getData('cc_number')) > 6) {
264
+ $card['bin'] = substr((string)$payment->getData('cc_number'), 0, 6);
265
+ }
266
+
267
+ return $card;
268
+ }
269
+
270
+ public function getAddress($address_object)
271
+ {
272
+ $address = array();
273
+
274
+ $address['streetAddress'] = $address_object->getStreet1();
275
+ $address['unit'] = null;
276
+
277
+ if ($address_object->getStreet2()) {
278
+ $address['unit'] = $address_object->getStreet2();
279
+ }
280
+
281
+ $address['city'] = $address_object->getCity();
282
+
283
+ $address['provinceCode'] = $address_object->getRegionCode();
284
+ $address['postalCode'] = $address_object->getPostcode();
285
+ $address['countryCode'] = $address_object->getCountryId();
286
+
287
+ $address['latitude'] = null;
288
+ $address['longitude'] = null;
289
+
290
+ return $address;
291
+ }
292
+
293
+ public function getBillingAddress()
294
+ {
295
+ return $this->getAddress($this->billing_address);
296
+ }
297
+
298
+ public function getShippingAddress()
299
+ {
300
+ return $this->getAddress($this->shipping_address);
301
+ }
302
+
303
+ public function getRecipient()
304
+ {
305
+ $recipient = array();
306
+
307
+ // In the case of non-shipped (ex: downloadable) orders, shipping address will be null so
308
+ // in that case, we need to avoid the exception.
309
+ if($this->shipping_address) {
310
+ $recipient['deliveryAddress'] = $this->getShippingAddress();
311
+ $recipient['fullName'] = $this->shipping_address->getFirstname() . ' ' . $this->shipping_address->getLastname();
312
+ $recipient['confirmationPhone'] = $this->shipping_address->getTelephone();
313
+ // Email: Note that this field is always the same for both addresses
314
+ $recipient['confirmationEmail'] = $this->shipping_address->getEmail();
315
+ }
316
+ // Some customers have reported seeing "n/a@na.na" come through instead of a valid or null address
317
+ // We suspect that it is due to an older version of Magento. If it becomes unnecessary, do remove the extra check.
318
+ if (!$recipient['confirmationEmail'] || $recipient['confirmationEmail'] == 'n/a@na.na') {
319
+ $recipient['confirmationEmail'] = $this->order->getCustomerEmail();
320
+ }
321
+
322
+
323
+ return $recipient;
324
+ }
325
+
326
+ public function getUserAccount()
327
+ {
328
+ $customer = $this->customer;
329
+
330
+ $user = array(
331
+ "emailAddress" => null,
332
+ "username" => null,
333
+ "phone" => null,
334
+ "createdDate" => null,
335
+ "accountNumber" => null,
336
+ "lastOrderId" => null,
337
+ "aggregateOrderCount" => null,
338
+ "aggregateOrderDollars" => null,
339
+ "lastUpdateDate" => null
340
+ );
341
+
342
+ if ($customer && $customer->getId()) {
343
+ $user['emailAddress'] = $customer->getEmail();
344
+
345
+ $user['phone'] = $this->billing_address->getTelephone();
346
+
347
+ $user['createdDate'] = date('c', strtotime($customer->getCreatedAt()));
348
+ $user['lastUpdateDate'] = date('c', strtotime($customer->getUpdatedAt()));
349
+
350
+ $user['accountNumber'] = $customer->getId();
351
+
352
+ $last_order_id = null;
353
+
354
+ $orders = Mage::getModel('sales/order')->getCollection()->addFieldToFilter('customer_id', $customer->getId());
355
+ $orders->getSelect()->order('created_at DESC');
356
+
357
+ $aggregate_total = 0.;
358
+ $order_count = 0;
359
+
360
+ foreach ($orders as $order) {
361
+ if ($last_order_id === null) {
362
+ $last_order_id = $order->getIncrementId();
363
+ }
364
+
365
+ $aggregate_total += floatval($order->getGrandTotal());
366
+ $order_count += 1;
367
+ }
368
+
369
+ $user['lastOrderId'] = $last_order_id;
370
+ $user['aggregateOrderCount'] = $order_count;
371
+ $user['aggregateOrderDollars'] = floatval($aggregate_total);
372
+ }
373
+
374
+ return $user;
375
+ }
376
+
377
+ public function getUrl()
378
+ {
379
+ if ($this->hasData('url')) {
380
+ return $this->getData('url');
381
+ }
382
+
383
+ return Mage::getStoreConfig('signifyd_connect/settings/url') . '/cases';
384
+ }
385
+
386
+ public function getAuth()
387
+ {
388
+ if ($this->hasData('auth')) {
389
+ return $this->getData('auth');
390
+ }
391
+
392
+ return Mage::getStoreConfig('signifyd_connect/settings/key');
393
+ }
394
+
395
+ public function submitCase($case)
396
+ {
397
+ $case = json_encode($case);
398
+
399
+ return Mage::helper('signifyd_connect')->request($this->getUrl(), $case, $this->getAuth(), 'application/json');
400
+ }
401
+
402
+ public function generateCase()
403
+ {
404
+ $case = array();
405
+
406
+ $case['purchase'] = $this->getPurchase();
407
+ $case['recipient'] = $this->getRecipient();
408
+ $case['card'] = $this->getCard();
409
+ $case['userAccount'] = $this->getUserAccount();
410
+
411
+ return $case;
412
+ }
413
+
414
+ public function getInvoiced($order)
415
+ {
416
+ $collection = $order->getInvoiceCollection();
417
+
418
+ foreach ($collection as $invoice) {
419
+ return true;
420
+ }
421
+
422
+ return false;
423
+ }
424
+
425
+ public function openCase($observer)
426
+ {
427
+ try {
428
+ if (!Mage::getStoreConfig('signifyd_connect/settings/enabled') && !$this->getEnabled()) {
429
+ return;
430
+ }
431
+
432
+ $event = $observer->getEvent();
433
+
434
+ if ($event->hasOrder()) {
435
+ $order = $event->getOrder();
436
+ } else if ($event->hasObject()) {
437
+ $order = $event->getObject();
438
+ }
439
+
440
+ $order_model = get_class(Mage::getModel('sales/order'));
441
+
442
+ if (!($order instanceof $order_model)) {
443
+ return;
444
+ }
445
+
446
+ if ($order && $order->getId()) {
447
+ if (Mage::helper('signifyd_connect')->isProcessed($order) && !$this->getForceProcess()) {
448
+ return;
449
+ }
450
+
451
+ $payments = $order->getPaymentsCollection();
452
+
453
+ foreach ($payments as $payment) {
454
+ $this->payment = $payment;
455
+ }
456
+
457
+ $method = $this->payment->getMethod();
458
+
459
+ $state = $order->getState();
460
+
461
+ if (!$state || $state == Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) {
462
+ return;
463
+ }
464
+
465
+ $this->order = $order;
466
+ $this->billing_address = $order->getBillingAddress();
467
+ $this->shipping_address = $order->getShippingAddress();
468
+
469
+ if ($order->getCustomer()) {
470
+ $this->customer = $order->getCustomer();
471
+ }
472
+
473
+ $this->quote = $order->getQuote();
474
+
475
+ if (!$this->quote) {
476
+ $this->quote = $order;
477
+ }
478
+
479
+ $case = $this->generateCase();
480
+
481
+ $case_object = Mage::helper('signifyd_connect')->markProcessed($order);
482
+
483
+ $response = $this->submitCase($case);
484
+
485
+ try {
486
+ $response_code = $response->getHttpCode();
487
+
488
+ if (substr($response_code, 0, 1) == '2') {
489
+ $response_data = json_decode($response->getRawResponse(), true);
490
+
491
+ $case_object = Mage::getModel('signifyd_connect/case')->load($case_object->getId());
492
+ $case_object->setUpdated(strftime('%Y-%m-%d %H:%M:%S', time()));
493
+ $case_object->setCode($response_data['investigationId']);
494
+ $case_object->save();
495
+ }
496
+ } catch (Exception $e) {
497
+
498
+ }
499
+ }
500
+ } catch (Exception $e) {
501
+ Mage::log($e->__toString(), null, 'signifyd_connect.log');
502
+ }
503
+ }
504
+
505
+ public function logData()
506
+ {
507
+ // Used to capture data for testing with
508
+
509
+ $order_data = json_encode($this->order->getData());
510
+ $billing_data = json_encode($this->order->getBillingAddress()->getData());
511
+ $shipping_data = json_encode($this->order->getShippingAddress()->getData());
512
+ $customer_data = json_encode($this->customer->getData());
513
+ $payment_data = json_encode($this->payment->getData());
514
+ $quote_data = json_encode($this->quote->getData());
515
+ $items = array();
516
+ $products = array();
517
+
518
+ foreach ($this->quote->getAllItems() as $item) {
519
+ $items[$item->getId()] = $item->getData();
520
+ $product = Mage::getModel('catalog/product')->load($item->getProductId());
521
+ $products[$item->getId()] = $product->getData();
522
+ }
523
+
524
+ $items = json_encode($items);
525
+ $products = json_encode($products);
526
+
527
+ Mage::log("Order:\n $order_data", null, 'signifyd_connect_objects.log');
528
+ Mage::log("Billing:\n $billing_data", null, 'signifyd_connect_objects.log');
529
+ Mage::log("Shipping:\n $shipping_data", null, 'signifyd_connect_objects.log');
530
+ Mage::log("Customer:\n $customer_data", null, 'signifyd_connect_objects.log');
531
+ Mage::log("Payment:\n $payment_data", null, 'signifyd_connect_objects.log');
532
+ Mage::log("Quote:\n $quote_data", null, 'signifyd_connect_objects.log');
533
+ Mage::log("Items:\n $items", null, 'signifyd_connect_objects.log');
534
+ Mage::log("Products:\n $products", null, 'signifyd_connect_objects.log');
535
+ }
536
+
537
+ public function getAdminRoute()
538
+ {
539
+ $route = false;
540
+
541
+ try {
542
+ // 1.4.0.0 support means we need to hard code these paths
543
+ if ((bool)(string)Mage::getConfig()->getNode('default/admin/url/use_custom_path')) {
544
+ $route = Mage::getConfig()->getNode('default/admin/url/custom_path');
545
+ } else {
546
+ $route = Mage::getConfig()->getNode('admin/routers/adminhtml/args/frontName');
547
+ }
548
+ } catch (Exception $e) {
549
+
550
+ }
551
+
552
+ if (!$route) {
553
+ $route = 'admin';
554
+ }
555
+
556
+ return $route;
557
+ }
558
+
559
+ public function eavCollectionAbstractLoadBefore($observer)
560
+ {
561
+ $x = $observer->getCollection();
562
+
563
+ $request = Mage::app()->getRequest();
564
+ $module = $request->getModuleName();
565
+ $controller = $request->getControllerName();
566
+ $action = $request->getActionName();
567
+
568
+ if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
569
+ return;
570
+ }
571
+
572
+ $clss = get_class($x);
573
+ if ($clss == 'Mage_Sales_Model_Mysql4_Order_Collection' || $clss == 'Mage_Sales_Model_Mysql4_Order_Grid_Collection') {
574
+ $observer->setOrderGridCollection($x);
575
+ return $this->salesOrderGridCollectionLoadBefore($observer);
576
+ }
577
+ }
578
+
579
+ public function coreCollectionAbstractLoadBefore($observer)
580
+ {
581
+ $x = $observer->getCollection();
582
+
583
+ $request = Mage::app()->getRequest();
584
+ $module = $request->getModuleName();
585
+ $controller = $request->getControllerName();
586
+ $action = $request->getActionName();
587
+
588
+ if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
589
+ return;
590
+ }
591
+
592
+ $clss = get_class($x);
593
+
594
+ if ($clss == 'Mage_Sales_Model_Mysql4_Order_Collection' || $clss == 'Mage_Sales_Model_Mysql4_Order_Grid_Collection') {
595
+ $observer->setOrderGridCollection($x);
596
+ return $this->salesOrderGridCollectionLoadBefore($observer);
597
+ }
598
+ }
599
+
600
+ public function isCe()
601
+ {
602
+ return !@class_exists('Enterprise_Cms_Helper_Data');
603
+ }
604
+
605
+ public function oldSupport()
606
+ {
607
+ $version = Mage::getVersion();
608
+
609
+ if ($this->isCe()) {
610
+ return version_compare($version, '1.4.1.0', '<');
611
+ } else {
612
+ return version_compare($version, '1.10.0.0', '<');
613
+ }
614
+
615
+ return false;
616
+ }
617
+
618
+ public function belowSix()
619
+ {
620
+ $version = Mage::getVersion();
621
+
622
+ if ($this->isCe()) {
623
+ return version_compare($version, '1.6.0.0', '<');
624
+ } else {
625
+ return version_compare($version, '1.11.0.0', '<');
626
+ }
627
+
628
+ return false;
629
+ }
630
+
631
+ public function salesOrderGridCollectionLoadBefore($observer)
632
+ {
633
+ if ($this->joins === 0) {
634
+ $request = Mage::app()->getRequest();
635
+ $module = $request->getModuleName();
636
+ $controller = $request->getControllerName();
637
+ $action = $request->getActionName();
638
+
639
+ if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
640
+ return;
641
+ }
642
+
643
+ $collection = $observer->getOrderGridCollection();
644
+ $select = $collection->getSelect();
645
+
646
+ if (Mage::getStoreConfig('signifyd_connect/advanced/show_scores')) {
647
+ if ($this->oldSupport()) {
648
+ $select->joinLeft(array('signifyd'=>$collection->getTable('signifyd_connect/case')), 'signifyd.order_increment=e.increment_id', array('score'=>'score'));
649
+ $this->joins++;
650
+ } else {
651
+ $select->joinLeft(array('signifyd'=>$collection->getTable('signifyd_connect/case')), 'signifyd.order_increment=main_table.increment_id', array('score'=>'score'));
652
+ $this->joins++;
653
+ }
654
+
655
+ Mage::log('joined');
656
+ }
657
+ }
658
+ }
659
+
660
+ public function coreBlockAbstractToHtmlBefore(Varien_Event_Observer $observer)
661
+ {
662
+ if (Mage::getStoreConfig('signifyd_connect/advanced/show_scores')) {
663
+ $request = Mage::app()->getRequest();
664
+ $module = $request->getModuleName();
665
+ $controller = $request->getControllerName();
666
+ $action = $request->getActionName();
667
+
668
+ if ($module != $this->getAdminRoute() || $controller != 'sales_order') {
669
+ return;
670
+ }
671
+
672
+ $helper = Mage::helper('signifyd_connect');
673
+ $block = $observer->getEvent()->getBlock();
674
+
675
+ if ($block->getId() == 'sales_order_grid') {
676
+ $block->addColumnAfter(
677
+ 'score',
678
+ array(
679
+ 'header' => $helper->__('Signifyd Score'),
680
+ 'align' => 'left',
681
+ 'type' => 'text',
682
+ 'index' => 'score',
683
+ 'filter' => false,
684
+ 'renderer' => 'signifyd_connect/renderer',
685
+ 'width' => '100px',
686
+ ),
687
+ 'status'
688
+ );
689
+
690
+ $block->sortColumnsByOrder();
691
+ }
692
+ }
693
+ }
694
+ }
app/code/community/Signifyd/Connect/etc/config.xml CHANGED
@@ -3,7 +3,7 @@
3
<config>
4
<modules>
5
<Signifyd_Connect>
6
- <version>3.4.8</version>
7
</Signifyd_Connect>
8
</modules>
9
<global>
3
<config>
4
<modules>
5
<Signifyd_Connect>
6
+ <version>3.6.0</version>
7
</Signifyd_Connect>
8
</modules>
9
<global>
app/code/community/Signifyd/Connect/sql/signifyd_connect_setup/mysql4-upgrade-3.4.8-3.4.9.php DELETED
@@ -1,8 +0,0 @@
1
- <?php
2
-
3
- try {
4
- $this->startSetup();
5
- $this->endSetup();
6
- } catch (Exception $e) {
7
- Mage::log('Signifyd_Connect upgrade: ' . $e->__toString(), null, 'signifyd_connect.log');
8
- }
package.xml CHANGED
@@ -1,7 +1,7 @@
1
<?xml version="1.0"?>
2
<package>
3
<name>Signifyd_Connect</name>
4
- <version>3.5.3</version>
5
<stability>stable</stability>
6
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL</license>
7
<channel>community</channel>
@@ -10,9 +10,9 @@
10
<description>Supports all versions of Magento</description>
11
<notes>Supports all versions of Magento</notes>
12
<authors><author><name>signifyd</name><user>auto-converted</user><email>manelis@signifyd.com</email></author></authors>
13
- <date>2015-04-18</date>
14
- <time>21:52:53</time>
15
- <contents><target name="mageetc"><dir name="modules"><file name="Signifyd_Connect.xml" hash="bcd998a24567eba8a20423c40fba2adf"/></dir></target><target name="magecommunity"><dir name="Signifyd"><dir name="Connect"><dir name="Block"><dir name="Adminhtml"><dir name="Sales"><dir name="Order"><file name="Grid.php" hash="fcdcd4cb2933147e4b573b4fb7217992"/></dir><file name="Order.php" hash="e49f869c0aa5fb3ab6b70fb5752049ac"/></dir></dir><file name="Renderer.php" hash="5564e9c6926afbbdade26a6fe746948a"/></dir><dir name="Controllers"><dir name="Adminhtml"><file name="SignifydController.php" hash="937fa40bfd59857c738691e0fc6594e7"/></dir><file name="ConnectController.php" hash="4d5cf9c36b3a72e8f1d1f80aa4752b26"/></dir><dir name="Helper"><file name="Data.php" hash="2b4ecd3e91506eed6d155f8f6e299507"/></dir><dir name="Model"><dir name="Resource"><dir name="Case"><file name="Collection.php" hash="b7dac9979a0c81db56294d1548570fc2"/></dir><file name="Case.php" hash="621fb50264bd0cdeba720dee6949a0bf"/></dir><file name="Case.php" hash="92e044f7414eddfe084320b4a2098cee"/><file name="Cron.php" hash="51665978bd2bcf67b493f2a2b450d1b8"/><file name="Link.php" hash="ecaf4c403a586b4b5c8b67c77f6ac433"/><file name="Observer.php" hash="e22012acac76ced188fdeae1833b64b1"/><file name="Setup.php" hash="e803ffb4b86c7d8ec1d149e665d65877"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="SignifydController.php" hash="937fa40bfd59857c738691e0fc6594e7"/></dir><file name="ConnectController.php" hash="4d5cf9c36b3a72e8f1d1f80aa4752b26"/></dir><dir name="etc"><file name="adminhtml.xml" hash="894bd3f5ac76e9f602ab6ab592648b03"/><file name="config.xml" hash="7a18e7f7d5b395882c8bf90b56724d8a"/><file name="system.xml" hash="dc115570682f75c6666d5b4657db729f"/></dir><dir name="sql"><dir name="signifyd_connect_setup"><file name="mysql4-install-3.1.1.php" hash="7fb2ccaf8352eea26e626ace6de53d80"/><file name="mysql4-install-3.3.0.php" hash="f61d0c018b28ae04d8d14b38556d18ad"/><file name="mysql4-install-3.4.0.php" hash="109cc5ca60974d0c4755dcb0f5ade3e7"/><file name="mysql4-install-3.4.5.php" hash="401b92235c0e534c941a64c60d24b851"/><file name="mysql4-upgrade-3.2.0-3.2.1.php" hash="9e36c608afd6e30e3052334e085eeff4"/><file name="mysql4-upgrade-3.2.1-3.2.2.php" hash="efcc5d46a41e549e508a693f1e77bf44"/><file name="mysql4-upgrade-3.2.2-3.2.3.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.2.3-3.3.0.php" hash="94b907c2cacde5fb9831408ce9a06190"/><file name="mysql4-upgrade-3.3.0-3.4.0.php" hash="6eb18705081483bb8d9c14adcdefd095"/><file name="mysql4-upgrade-3.4.0-3.4.1.php" hash="79f2064f1fa20d646e66aa3e7912d2a0"/><file name="mysql4-upgrade-3.4.1-3.4.2.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.2-3.4.3.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.3-3.4.4.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.4-3.4.5.php" hash="5b7507d6bb97bf44d27b7a89c56924bb"/><file name="mysql4-upgrade-3.4.5-3.4.6.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.6-3.4.7.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.7-3.4.8.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.8-3.4.9.php" hash="3ceb86495f33475774d4fc8727254cfc"/></dir></dir></dir></dir></target></contents>
16
<compatible/>
17
<dependencies/>
18
</package>
1
<?xml version="1.0"?>
2
<package>
3
<name>Signifyd_Connect</name>
4
+ <version>3.6.0</version>
5
<stability>stable</stability>
6
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL</license>
7
<channel>community</channel>
10
<description>Supports all versions of Magento</description>
11
<notes>Supports all versions of Magento</notes>
12
<authors><author><name>signifyd</name><user>auto-converted</user><email>manelis@signifyd.com</email></author></authors>
13
+ <date>2015-05-17</date>
14
+ <time>02:27:32</time>
15
+ <contents><target name="mageetc"><dir name="modules"><file name="Signifyd_Connect.xml" hash="bcd998a24567eba8a20423c40fba2adf"/></dir></target><target name="magecommunity"><dir name="Signifyd"><dir name="Connect"><dir name="Block"><dir name="Adminhtml"><dir name="Sales"><dir name="Order"><file name="Grid.php" hash="fcdcd4cb2933147e4b573b4fb7217992"/></dir><file name="Order.php" hash="e49f869c0aa5fb3ab6b70fb5752049ac"/></dir></dir><file name="Renderer.php" hash="5564e9c6926afbbdade26a6fe746948a"/></dir><dir name="Helper"><file name="Data.php" hash="2b4ecd3e91506eed6d155f8f6e299507"/></dir><dir name="Model"><dir name="Resource"><dir name="Case"><file name="Collection.php" hash="b7dac9979a0c81db56294d1548570fc2"/></dir><file name="Case.php" hash="621fb50264bd0cdeba720dee6949a0bf"/></dir><file name="Case.php" hash="92e044f7414eddfe084320b4a2098cee"/><file name="Cron.php" hash="51665978bd2bcf67b493f2a2b450d1b8"/><file name="Link.php" hash="ecaf4c403a586b4b5c8b67c77f6ac433"/><file name="Observer.php" hash="65f9e1b5b41f6281a402b42fa5621b04"/><file name="Setup.php" hash="e803ffb4b86c7d8ec1d149e665d65877"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="SignifydController.php" hash="937fa40bfd59857c738691e0fc6594e7"/></dir><file name="ConnectController.php" hash="4d5cf9c36b3a72e8f1d1f80aa4752b26"/></dir><dir name="etc"><file name="adminhtml.xml" hash="894bd3f5ac76e9f602ab6ab592648b03"/><file name="config.xml" hash="34dbad6194e5aa3c294cddab92744a69"/><file name="system.xml" hash="dc115570682f75c6666d5b4657db729f"/></dir><dir name="sql"><dir name="signifyd_connect_setup"><file name="mysql4-install-3.1.1.php" hash="7fb2ccaf8352eea26e626ace6de53d80"/><file name="mysql4-install-3.3.0.php" hash="f61d0c018b28ae04d8d14b38556d18ad"/><file name="mysql4-install-3.4.0.php" hash="109cc5ca60974d0c4755dcb0f5ade3e7"/><file name="mysql4-install-3.4.5.php" hash="401b92235c0e534c941a64c60d24b851"/><file name="mysql4-upgrade-3.2.0-3.2.1.php" hash="9e36c608afd6e30e3052334e085eeff4"/><file name="mysql4-upgrade-3.2.1-3.2.2.php" hash="efcc5d46a41e549e508a693f1e77bf44"/><file name="mysql4-upgrade-3.2.2-3.2.3.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.2.3-3.3.0.php" hash="94b907c2cacde5fb9831408ce9a06190"/><file name="mysql4-upgrade-3.3.0-3.4.0.php" hash="6eb18705081483bb8d9c14adcdefd095"/><file name="mysql4-upgrade-3.4.0-3.4.1.php" hash="79f2064f1fa20d646e66aa3e7912d2a0"/><file name="mysql4-upgrade-3.4.1-3.4.2.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.2-3.4.3.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.3-3.4.4.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.4-3.4.5.php" hash="5b7507d6bb97bf44d27b7a89c56924bb"/><file name="mysql4-upgrade-3.4.5-3.4.6.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.6-3.4.7.php" hash="3ceb86495f33475774d4fc8727254cfc"/><file name="mysql4-upgrade-3.4.7-3.4.8.php" hash="3ceb86495f33475774d4fc8727254cfc"/></dir></dir></dir></dir></target></contents>
16
<compatible/>
17
<dependencies/>
18
</package>