Bitbull_Satispay - Version 0.2.0

Version Notes

First stable version.

Download this release

Release Info

Developer Renato Cason
Extension Bitbull_Satispay
Version 0.2.0
Comparing to
See all releases


Version 0.2.0

Files changed (28) hide show
  1. app/code/community/Bitbull/Satispay/Block/Payment/Form.php +19 -0
  2. app/code/community/Bitbull/Satispay/Block/Payment/Info.php +19 -0
  3. app/code/community/Bitbull/Satispay/Block/Payment/Page.php +102 -0
  4. app/code/community/Bitbull/Satispay/Helper/Data.php +85 -0
  5. app/code/community/Bitbull/Satispay/Helper/Order.php +79 -0
  6. app/code/community/Bitbull/Satispay/Helper/Phone.php +31 -0
  7. app/code/community/Bitbull/Satispay/Model/Cron.php +44 -0
  8. app/code/community/Bitbull/Satispay/Model/Logger.php +134 -0
  9. app/code/community/Bitbull/Satispay/Model/Payment.php +194 -0
  10. app/code/community/Bitbull/Satispay/Model/Session.php +9 -0
  11. app/code/community/Bitbull/Satispay/Model/System/Config/Source/Countrycode.php +15 -0
  12. app/code/community/Bitbull/Satispay/controllers/PaymentController.php +180 -0
  13. app/code/community/Bitbull/Satispay/etc/config.xml +82 -0
  14. app/code/community/Bitbull/Satispay/etc/system.xml +81 -0
  15. app/design/adminhtml/base/default/template/bitbull/satispay/payment/info.phtml +3 -0
  16. app/design/frontend/base/default/layout/bitbull/satispay.xml +19 -0
  17. app/design/frontend/base/default/template/bitbull/satispay/payment/form.phtml +9 -0
  18. app/design/frontend/base/default/template/bitbull/satispay/payment/info.phtml +5 -0
  19. app/design/frontend/base/default/template/bitbull/satispay/payment/page.phtml +26 -0
  20. app/etc/modules/Bitbull_Satispay.xml +10 -0
  21. app/locale/en_US/Bitbull_Satispay.csv +6 -0
  22. app/locale/it_IT/Bitbull_Satispay.csv +6 -0
  23. lib/Satispay/Core/.gitkeep +0 -0
  24. lib/Satispay/Core/Client.php +146 -0
  25. package.xml +18 -0
  26. skin/frontend/base/default/bitbull/satispay/css/payment.css +44 -0
  27. skin/frontend/base/default/bitbull/satispay/images/satispay_logo.png +0 -0
  28. skin/frontend/base/default/bitbull/satispay/js/payment.js +54 -0
app/code/community/Bitbull/Satispay/Block/Payment/Form.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Block_Payment_Form extends Mage_Payment_Block_Form
4
+ {
5
+ /**
6
+ * Block construction. Set block template.
7
+ */
8
+ protected function _construct()
9
+ {
10
+ parent::_construct();
11
+ $this->setTemplate('bitbull/satispay/payment/form.phtml');
12
+ }
13
+
14
+ public function getInstructions()
15
+ {
16
+ return Mage::helper('satispay')
17
+ ->getInstructions();
18
+ }
19
+ }
app/code/community/Bitbull/Satispay/Block/Payment/Info.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Block_Payment_Info extends Mage_Payment_Block_Info
4
+ {
5
+ /**
6
+ * Block construction. Set block template.
7
+ */
8
+ protected function _construct()
9
+ {
10
+ parent::_construct();
11
+ $this->setTemplate('bitbull/satispay/payment/info.phtml');
12
+ }
13
+
14
+ protected function getTitle()
15
+ {
16
+ return Mage::helper('satispay')
17
+ ->getTitle();
18
+ }
19
+ }
app/code/community/Bitbull/Satispay/Block/Payment/Page.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Block_Payment_Page extends Mage_Core_Block_Template
4
+ {
5
+ protected $_session;
6
+ protected $_order;
7
+
8
+ /**
9
+ * Return satispay session singleton
10
+ */
11
+ protected function getSession()
12
+ {
13
+ if(is_null($this->_session)) {
14
+ $this->_session = Mage::getSingleton('satispay/session');
15
+ }
16
+
17
+ return $this->_session;
18
+ }
19
+
20
+
21
+ /**
22
+ * Return current order model
23
+ */
24
+ protected function getOrder()
25
+ {
26
+ if(is_null($this->_order)) {
27
+ $session = $this->getSession();
28
+ $this->_order = Mage::getModel('sales/order')
29
+ ->load($session->getOrderId(), 'increment_id');
30
+ }
31
+
32
+ return $this->_order;
33
+ }
34
+
35
+ /**
36
+ * Return telephone number set on billing address
37
+ */
38
+ protected function getBillingTelephone()
39
+ {
40
+ $telephone = '';
41
+
42
+ $order = $this->getOrder();
43
+ if($order && ($billing = $order->getBillingAddress())) {
44
+ $telephone = $billing->getTelephone();
45
+ }
46
+
47
+ return $telephone;
48
+ }
49
+
50
+ /**
51
+ * Return country codes list
52
+ */
53
+ public function getCountryCodes()
54
+ {
55
+ return Mage::helper('satispay/phone')
56
+ ->getCountryCodes();
57
+ }
58
+
59
+ /**
60
+ * Return country code from billing telephone number if set,
61
+ * and the configuration default one otherwise
62
+ */
63
+ public function getDefaultCountryCode()
64
+ {
65
+ // Try to get the country code from billing telephone
66
+ $telephone = $this->getBillingTelephone();
67
+
68
+ if($telephone) {
69
+ $countryCodes = $this->getCountryCodes();
70
+ foreach($countryCodes as $countryCode) {
71
+ $l = strlen($countryCode);
72
+ if(substr($telephone, 0, $l) == $countryCode) {
73
+ return $countryCode;
74
+ }
75
+ }
76
+ }
77
+
78
+ // Return default from configuration
79
+ return Mage::helper('satispay')
80
+ ->getDefaultCountryCode();
81
+ }
82
+
83
+ /**
84
+ * Return phone number from billing telephone
85
+ * removing country prefix if necessary
86
+ */
87
+ public function getPhoneNumber()
88
+ {
89
+ $telephone = $this->getBillingTelephone();
90
+ if(!$telephone) {
91
+ return '';
92
+ }
93
+
94
+ $countryCode = $this->getDefaultCountryCode();
95
+ $l = strlen($countryCode);
96
+ if(substr($telephone, 0, $l) == $countryCode) {
97
+ $telephone = substr($telephone, $l);
98
+ }
99
+
100
+ return $telephone;
101
+ }
102
+ }
app/code/community/Bitbull/Satispay/Helper/Data.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Bitbull_Satispay_Helper_Data extends Mage_Core_Helper_Abstract
3
+ {
4
+ /**
5
+ * XML Paths for configuration constants
6
+ */
7
+ const XML_PATH_PAYMENT_SATISPAY_ACTIVE = 'payment/satispay/active';
8
+ const XML_PATH_PAYMENT_SATISPAY_INSTRUCTIONS = 'payment/satispay/instructions';
9
+ const XML_PATH_PAYMENT_SATISPAY_TITLE = 'payment/satispay/title';
10
+ const XML_PATH_PAYMENT_SATISPAY_STAGING = 'payment/satispay/staging';
11
+ const XML_PATH_PAYMENT_SATISPAY_SECURITY_TOKEN = 'payment/satispay/security_token';
12
+ const XML_PATH_PAYMENT_SATISPAY_DEFAULT_COUNTRY_CODE = 'payment/satispay/default_country_code';
13
+ const XML_PATH_PAYMENT_SATISPAY_DEBUG = 'payment/satispay/debug';
14
+
15
+ /** @var Bitbull_Satispay_Model_Logger */
16
+ protected $_logger;
17
+
18
+ /** @var array */
19
+ protected $_supportedCurrencyCodes = array('EUR');
20
+
21
+ public function __construct()
22
+ {
23
+ $this->_logger = Mage::getModel('satispay/logger', $this->isDebug());
24
+ }
25
+
26
+ public function isActive()
27
+ {
28
+ return Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_SATISPAY_ACTIVE);
29
+ }
30
+
31
+ public function getTitle()
32
+ {
33
+ return Mage::getStoreConfig(self::XML_PATH_PAYMENT_SATISPAY_TITLE);
34
+ }
35
+ public function getInstructions()
36
+ {
37
+ return Mage::getStoreConfig(self::XML_PATH_PAYMENT_SATISPAY_INSTRUCTIONS);
38
+ }
39
+
40
+ public function getStaging()
41
+ {
42
+ return Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_SATISPAY_STAGING);
43
+ }
44
+
45
+ public function getSecurityToken()
46
+ {
47
+ return Mage::getStoreConfig(self::XML_PATH_PAYMENT_SATISPAY_SECURITY_TOKEN);
48
+ }
49
+
50
+ public function getDefaultCountryCode()
51
+ {
52
+ return Mage::getStoreConfig(self::XML_PATH_PAYMENT_SATISPAY_DEFAULT_COUNTRY_CODE);
53
+ }
54
+
55
+ public function isDebug()
56
+ {
57
+ return Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_SATISPAY_DEBUG);
58
+ }
59
+
60
+ public function getClient() {
61
+ $client = new Satispay_Core_Client();
62
+
63
+ return $client->setStaging($this->getStaging())
64
+ ->setSecurityToken($this->getSecurityToken());
65
+ }
66
+
67
+ /**
68
+ * Check whether specified currency code is supported or not
69
+ *
70
+ * @param string $code
71
+ * @return bool
72
+ */
73
+ public function isCurrencyCodeSupported($code)
74
+ {
75
+ return in_array($code, $this->_supportedCurrencyCodes);
76
+ }
77
+
78
+ /**
79
+ * @return Bitbull_Satispay_Model_Logger
80
+ */
81
+ public function getLogger()
82
+ {
83
+ return $this->_logger;
84
+ }
85
+ }
app/code/community/Bitbull/Satispay/Helper/Order.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Bitbull_Satispay_Helper_Order extends Mage_Core_Helper_Abstract
3
+ {
4
+ /**
5
+ * Update order status according to charge status
6
+ */
7
+ public function update($order, $chargeId=null) {
8
+ // Check order status
9
+ if($order->getStatus() != Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) {
10
+ throw new Exception('Invalid order status: ' . $order->getStatus());
11
+ }
12
+
13
+ // Load chargeId from payment if not set
14
+ if(!$chargeId) {
15
+ $chargeId = $order->getPayment()
16
+ ->getLastTransId();
17
+ }
18
+
19
+ if(!$chargeId) {
20
+ throw new Exception('Could not load charge id from transaction');
21
+ }
22
+
23
+ // Check transaction status
24
+ $helper = Mage::helper('satispay');
25
+ $charge = $helper->getClient()
26
+ ->chargeGet($chargeId);
27
+
28
+ if(!$charge || !isset($charge->id)) {
29
+ $helper->getLogger()->err('Invalid server response for charge #' . $chargeId);
30
+ $helper->getLogger()->err($charge);
31
+
32
+ throw new Exception('Invalid server response');
33
+ }
34
+
35
+ // Update order
36
+ $helper->getLogger()->info('Updating order ' . $order->getIncrementId() . ' from charge ' . $chargeId);
37
+ $helper->getLogger()->info($charge);
38
+
39
+ // Handle order update depending on payment status
40
+ if($charge->status == Satispay_Core_Client::PAYMENT_STATUS_SUCCEESS) {
41
+ $helper->getLogger()->info('Payment succeeded: invoicing order');
42
+
43
+ // Update order status
44
+ $order->setState(Mage_Sales_Model_Order::STATE_PROCESSING);
45
+ $order->setStatus(Mage_Sales_Model_Order::STATE_PROCESSING);
46
+ $order->addStatusHistoryComment('Charge in ' . $charge->status . ' status.');
47
+ $order->sendNewOrderEmail();
48
+ $order->save();
49
+
50
+ // Generate invoice
51
+ $invoice = Mage::getModel('sales/service_order', $order)
52
+ ->prepareInvoice();
53
+
54
+ if (!$invoice->getTotalQty()) {
55
+ $helper->getLogger()->err('Skipping invoicing for order ' . $order->getIncrementId() . ': invalid total quantity');
56
+ return;
57
+ }
58
+
59
+ $invoice->setTransactionId($chargeId);
60
+ $invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_ONLINE);
61
+ $invoice->register();
62
+ $transactionSave = Mage::getModel('core/resource_transaction')
63
+ ->addObject($invoice)
64
+ ->addObject($invoice->getOrder());
65
+
66
+ $transactionSave->save();
67
+
68
+ } elseif(in_array($charge->status, array(Satispay_Core_Client::PAYMENT_STATUS_DECLINED, Satispay_Core_Client::PAYMENT_STATUS_FAILURE))) {
69
+ $helper->getLogger()->info('Charge in ' . $charge->status . ' status: cancelling order');
70
+
71
+ $order->cancel();
72
+ $order->addStatusHistoryComment('Charge in ' . $charge->status . ' status.');
73
+ $order->save();
74
+
75
+ } else {
76
+ $helper->getLogger()->info('No action taken for status ' . $charge->status);
77
+ }
78
+ }
79
+ }
app/code/community/Bitbull/Satispay/Helper/Phone.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Helper_Phone extends Mage_Core_Helper_Abstract {
4
+ public function getCountryCodes() {
5
+ return array(
6
+ '+1', '+7', '+20', '+27', '+30', '+31', '+32', '+33', '+34', '+36', '+39',
7
+ '+40', '+41', '+43', '+44', '+45', '+46', '+47', '+48', '+49', '+51', '+52',
8
+ '+53', '+54', '+55', '+56', '+57', '+58', '+60', '+61', '+62', '+63', '+64',
9
+ '+65', '+66', '+81', '+82', '+84', '+86', '+90', '+91', '+92', '+93', '+94',
10
+ '+95', '+98', '+211', '+212', '+213', '+216', '+218', '+220', '+221', '+222',
11
+ '+223', '+224', '+225', '+226', '+227', '+228', '+229', '+230', '+231', '+232',
12
+ '+233', '+234', '+235', '+236', '+237', '+238', '+239', '+240', '+241', '+242',
13
+ '+243', '+244', '+245', '+246', '+248', '+249', '+250', '+251', '+252', '+253',
14
+ '+254', '+255', '+256', '+257', '+258', '+260', '+261', '+262', '+263', '+264',
15
+ '+265', '+266', '+267', '+268', '+269', '+290', '+291', '+297', '+298', '+299',
16
+ '+350', '+351', '+352', '+353', '+354', '+355', '+356', '+357', '+358', '+359',
17
+ '+370', '+371', '+372', '+373', '+374', '+375', '+376', '+377', '+378', '+380',
18
+ '+381', '+382', '+385', '+386', '+387', '+389', '+420', '+421', '+423', '+500',
19
+ '+501', '+502', '+503', '+504', '+505', '+506', '+507', '+508', '+509', '+590',
20
+ '+591', '+592', '+593', '+594', '+595', '+596', '+597', '+598', '+599', '+670',
21
+ '+672', '+673', '+674', '+675', '+676', '+677', '+678', '+679', '+680', '+681',
22
+ '+682', '+683', '+685', '+686', '+687', '+688', '+689', '+690', '+691', '+692',
23
+ '+850', '+852', '+853', '+855', '+856', '+880', '+886', '+960', '+961', '+962',
24
+ '+963', '+964', '+965', '+966', '+967', '+968', '+970', '+971', '+972', '+973',
25
+ '+974', '+975', '+976', '+977', '+992', '+993', '+994', '+995', '+996', '+998',
26
+ '+1242', '+1246', '+1264', '+1268', '+1284', '+1340', '+1345', '+1441', '+1473',
27
+ '+1649', '+1664', '+1670', '+1671', '+1684', '+1721', '+1758', '+1767', '+1784',
28
+ '+1868', '+1869', '+1876'
29
+ );
30
+ }
31
+ }
app/code/community/Bitbull/Satispay/Model/Cron.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Model_Cron {
4
+ /**
5
+ * Process pending orders with Satispay method
6
+ */
7
+ public function processPendingOrders() {
8
+ $helper = Mage::helper('satispay');
9
+ if(!$helper->isActive()) {
10
+ return;
11
+ }
12
+
13
+ $helper->getLogger()->info('Pending orders cron started');
14
+
15
+ // Get the list of pending orders
16
+ $collection = Mage::getModel('sales/order')->getCollection()
17
+ ->join(
18
+ array('payment' => 'sales/order_payment'),
19
+ 'main_table.entity_id=payment.parent_id',
20
+ array('payment_method' => 'payment.method')
21
+ );
22
+
23
+ // Add base filters to collection
24
+ $collection
25
+ ->addFieldToFilter('payment.method', 'satispay')
26
+ ->addFieldToFilter('status', Mage_Sales_Model_Order::STATE_PENDING_PAYMENT);
27
+
28
+ // Load collection
29
+ $collection->load();
30
+ $helper->getLogger()->info('Loaded ' . $collection->count() . ' orders');
31
+
32
+ // Process orders
33
+ $orderHelper = Mage::helper('satispay/order');
34
+ foreach($collection as $order) {
35
+ try {
36
+
37
+ $orderHelper->update($order);
38
+
39
+ } catch(Exception $ex) {
40
+ $helper->getLogger()->err('Error in pending orders cron job: ' . $ex->getMessage());
41
+ }
42
+ }
43
+ }
44
+ }
app/code/community/Bitbull/Satispay/Model/Logger.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Bitbull_Satispay_Model_Logger extends Mage_Core_Model_Abstract
3
+ {
4
+ /**
5
+ * Store flag to force logging
6
+ *
7
+ * @var string
8
+ */
9
+ protected $_force = false;
10
+
11
+ /**
12
+ * Log file name
13
+ */
14
+ protected $_filename = 'Bitbull_Satispay.log';
15
+
16
+ /**
17
+ * @var Mage_Core_Model_Logger
18
+ */
19
+ private $_logger;
20
+
21
+ /**
22
+ * Standard constructor.
23
+ */
24
+ public function __construct($parameters)
25
+ {
26
+ if (is_bool($parameters)) {
27
+ $this->_force = $parameters;
28
+ }
29
+
30
+ $this->_logger = Mage::getModel('core/logger');
31
+ }
32
+
33
+ protected function _log($message, $level, $force)
34
+ {
35
+ if (is_null($force)) {
36
+ $force = $this->_force;
37
+ }
38
+
39
+ return $this->_logger->log($message, $level, $this->_filename, $force);
40
+ }
41
+
42
+ /**
43
+ * Use to log debug messages.
44
+ *
45
+ * Debugging messages bring extended information about application processing.
46
+ * Such messages usually report calls of important functions along with results they return
47
+ * and values of specific variables or parameters.
48
+ */
49
+ public function debug($message, $force = null)
50
+ {
51
+ return $this->_log($message, Zend_Log::DEBUG, $force);
52
+ }
53
+
54
+ /**
55
+ * Use to log informative messages.
56
+ *
57
+ * Informative messages are usually used for reporting significant application progress and stages.
58
+ * Informative messages should not be reported too frequently because they can quickly become noise.
59
+ */
60
+ public function info($message, $force = null)
61
+ {
62
+ return $this->_log($message, Zend_Log::INFO, $force);
63
+ }
64
+
65
+ /**
66
+ * Use to log normal but significant condition.
67
+ */
68
+ public function notice($message, $force = null)
69
+ {
70
+ return $this->_log($message, Zend_Log::NOTICE, $force);
71
+ }
72
+
73
+ /**
74
+ * Use to log that application encountered warning conditions.
75
+ *
76
+ * Such messages are reported when something unusual happened that is not critical to process,
77
+ * but it would be useful to review this situation to decide if it should be resolved.
78
+ */
79
+ public function warn($message, $force = null)
80
+ {
81
+ return $this->_log($message, Zend_Log::WARN, $force);
82
+ }
83
+
84
+ /**
85
+ * Use to log that application encountered error conditions.
86
+ *
87
+ * A problem occurred while processing the current operation.
88
+ * Such a message usually requires the user to interact with the application or research the problem
89
+ * in order to find the reason and resolve it.
90
+ */
91
+ public function err($message, $force = null)
92
+ {
93
+ return $this->_log($message, Zend_Log::ERR, $force);
94
+ }
95
+
96
+ /**
97
+ * Use to log that application is in critical conditions.
98
+ *
99
+ * A critical problem occurred while processing the current operation.
100
+ * The application is in a critical state and cannot proceed with the execution of the current operation.
101
+ * In this case, the application usually reports such message and terminates.
102
+ * Such a message usually requires the user to interact with the application or research the problem
103
+ * in order to find the reason and resolve it.
104
+ */
105
+ public function crit($message, $force = null)
106
+ {
107
+ return $this->_log($message, Zend_Log::CRIT, $force);
108
+ }
109
+
110
+ /**
111
+ * Use to log that an action must be taken immediately.
112
+ *
113
+ * A very critical problem occurred while processing the current operation.
114
+ * Such a message usually requires the user to interact urgently with the application or research the problem
115
+ * in order to find the reason and resolve it.
116
+ */
117
+ public function alert($message, $force = null)
118
+ {
119
+ return $this->_log($message, Zend_Log::ALERT, $force);
120
+ }
121
+
122
+ /**
123
+ * Use to log that system is unusable.
124
+ *
125
+ * The application is in an unusable state and cannot proceed with the execution of the current operation.
126
+ * In this case, the application usually reports such message and terminates.
127
+ * Such a message usually requires the user to interact immediately with the application or research the problem
128
+ * in order to find the reason and resolve it.
129
+ */
130
+ public function emerg($message, $force = null)
131
+ {
132
+ return $this->_log($message, Zend_Log::EMERG, $force);
133
+ }
134
+ }
app/code/community/Bitbull/Satispay/Model/Payment.php ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Model_Payment extends Mage_Payment_Model_Method_Abstract
4
+ {
5
+ protected $_code = 'satispay';
6
+ protected $_formBlockType = 'satispay/payment_form';
7
+ protected $_infoBlockType = 'satispay/payment_info';
8
+ protected $_isInitializeNeeded = true;
9
+ protected $_canUseInternal = false;
10
+ protected $_canRefund = true;
11
+ protected $_canRefundInvoicePartial = true;
12
+
13
+ /**
14
+ * Whether current operation is order placement
15
+ *
16
+ * @return bool
17
+ */
18
+ private function _isPlaceOrder()
19
+ {
20
+ $info = $this->getInfoInstance();
21
+ if ($info instanceof Mage_Sales_Model_Quote_Payment) {
22
+ return false;
23
+ } elseif ($info instanceof Mage_Sales_Model_Order_Payment) {
24
+ return true;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Order increment ID getter (either real from order or a reserved from quote)
30
+ *
31
+ * @return string
32
+ */
33
+ private function _getOrderId()
34
+ {
35
+ $info = $this->getInfoInstance();
36
+
37
+ if ($this->_isPlaceOrder()) {
38
+ return $info->getOrder()->getIncrementId();
39
+ } else {
40
+ if (!$info->getQuote()->getReservedOrderId()) {
41
+ $info->getQuote()->reserveOrderId();
42
+ }
43
+ return $info->getQuote()->getReservedOrderId();
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Currency getter
49
+ *
50
+ * @return string
51
+ */
52
+ private function _getCurrency()
53
+ {
54
+ $info = $this->getInfoInstance();
55
+ if ($this->_isPlaceOrder()) {
56
+ return $info->getOrder()->getBaseCurrencyCode();
57
+ } else {
58
+ return $info->getQuote()->getQuoteBaseCurrencyCode();
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Grand total getter
64
+ *
65
+ * @return float
66
+ */
67
+ private function _getAmount()
68
+ {
69
+ $info = $this->getInfoInstance();
70
+ if ($this->_isPlaceOrder()) {
71
+ return (float)$info->getOrder()->getQuoteBaseGrandTotal();
72
+ } else {
73
+ return (float)$info->getQuote()->getBaseGrandTotal();
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Whether method is available for specified currency
79
+ *
80
+ * @param string $currencyCode
81
+ * @return bool
82
+ */
83
+ public function canUseForCurrency($currencyCode)
84
+ {
85
+ return Mage::helper('satispay')->isCurrencyCodeSupported($currencyCode);
86
+ }
87
+
88
+ /**
89
+ * Validate payment method information object
90
+ *
91
+ * @return Bitbull_Satispay_Model_Payment
92
+ */
93
+ public function validate()
94
+ {
95
+ parent::validate();
96
+
97
+ $helper = Mage::helper('satispay');
98
+ if(!$helper->getStaging() && !$helper->getSecurityToken()) {
99
+ $helper->getLogger()->err('Satispay security token is not set.');
100
+ Mage::throwException($helper->__('Satispay security token is not set.'));
101
+ }
102
+
103
+ return $this;
104
+ }
105
+
106
+ /**
107
+ * Method that will be executed instead of authorize or capture
108
+ * if flag isInitializeNeeded set to true
109
+ *
110
+ * @param string $paymentAction
111
+ * @param object $stateObject
112
+ *
113
+ * @return Bitbull_Satispay_Model_Payment
114
+ */
115
+ public function initialize($paymentAction, $stateObject)
116
+ {
117
+ // Transaction informations
118
+ $orderId = $this->_getOrderId();
119
+ $currency = $this->_getCurrency();
120
+ $amount = $this->_getAmount();
121
+
122
+ $helper = Mage::helper('satispay');
123
+ $helper->getLogger()->info('Payment initialization');
124
+ $helper->getLogger()->info('Order ID: ' . $orderId);
125
+ $helper->getLogger()->info('Currency: ' . $currency);
126
+ $helper->getLogger()->info('Amount: ' . $amount);
127
+
128
+ // Clear session to avoid collisions
129
+ $session = Mage::getSingleton('satispay/session');
130
+ $session->clear();
131
+
132
+ // Store transaction informations in session
133
+ $session->setOrderId($orderId)
134
+ ->setCurrency($currency)
135
+ ->setAmount(round($amount * 100));
136
+
137
+ return $this;
138
+ }
139
+
140
+ /**
141
+ * Return Order place redirect url
142
+ *
143
+ * @return string
144
+ */
145
+ public function getOrderPlaceRedirectUrl()
146
+ {
147
+ Mage::helper('satispay')->getLogger()
148
+ ->info('Redirecting customer to payment page');
149
+
150
+ return Mage::getUrl('satispay/payment/index', array(
151
+ '_secure'=>true
152
+ ));
153
+ }
154
+
155
+ /**
156
+ * Refund specified amount
157
+ *
158
+ * @param Varien_Object $payment
159
+ * @param float $amount
160
+ *
161
+ * @return Bitbull_Satispay_Model_Payment
162
+ */
163
+ public function refund(Varien_Object $payment, $amount)
164
+ {
165
+ $chargeId = $payment->getLastTransId();
166
+ if($chargeId) {
167
+
168
+ $helper = Mage::helper('satispay');
169
+ $client = $helper->getClient();
170
+
171
+ $helper->getLogger()->info('Issuing a refund for charge ' . $chargeId);
172
+ $refund = $client->refundCreate(
173
+ $chargeId,
174
+ $payment->getOrder()->getBaseCurrencyCode(),
175
+ round($amount * 100)
176
+ );
177
+
178
+ if(!$refund || !isset($refund->id)) {
179
+ $helper->getLogger()->err('Error issuing a refund for charge ' . $chargeId);
180
+ $helper->getLogger()->err($refund);
181
+
182
+ Mage::throwException(($refund && isset($refund->message)) ? $refund->message : 'Invalid server response');
183
+ }
184
+
185
+ $helper->getLogger()->info('Refund issued successfully');
186
+ $helper->getLogger()->info($refund);
187
+
188
+ } else {
189
+ Mage::throwException('Charge ID not set for the payment');
190
+ }
191
+
192
+ return $this;
193
+ }
194
+ }
app/code/community/Bitbull/Satispay/Model/Session.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Model_Session extends Mage_Core_Model_Session_Abstract
4
+ {
5
+ public function __construct()
6
+ {
7
+ $this->init('satispay');
8
+ }
9
+ }
app/code/community/Bitbull/Satispay/Model/System/Config/Source/Countrycode.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_Model_System_Config_Source_Countrycode {
4
+ public function toOptionArray() {
5
+ $countryCodes = Mage::helper('satispay/phone')
6
+ ->getCountryCodes();
7
+
8
+ $options = array();
9
+ foreach($countryCodes as $countryCode) {
10
+ $options[$countryCode] = $countryCode;
11
+ }
12
+
13
+ return $options;
14
+ }
15
+ }
app/code/community/Bitbull/Satispay/controllers/PaymentController.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bitbull_Satispay_PaymentController extends Mage_Core_Controller_Front_Action {
4
+ /**
5
+ * Payment index page
6
+ */
7
+ public function indexAction() {
8
+ $helper = Mage::helper('satispay');
9
+ $session = Mage::getSingleton('satispay/session');
10
+
11
+ // Check session parameters
12
+ if(!$session->getOrderId() || !$session->getCurrency() || !$session->getAmount()) {
13
+ $helper->getLogger()->err('Access to payment page with invalid session');
14
+ $helper->getLogger()->err($session->getData());
15
+
16
+ return $this->_redirect('checkout/cart/index');
17
+ }
18
+
19
+ $helper->getLogger()->info('Loading payment page');
20
+ $helper->getLogger()->info($session->getData());
21
+
22
+ $this->loadLayout();
23
+ $this->renderLayout();
24
+ }
25
+
26
+ /**
27
+ * Charge the selected user
28
+ */
29
+ public function charge_userAction() {
30
+ $helper = Mage::helper('satispay');
31
+ $session = Mage::getSingleton('satispay/session');
32
+
33
+ // Check session parameters
34
+ if(!$session->getOrderId() || !$session->getCurrency() || !$session->getAmount()) {
35
+ $helper->getLogger()->err('Called charge_user action with invalid session');
36
+ $helper->getLogger()->err($session->getData());
37
+
38
+ return $this->renderAjaxResponse(array(
39
+ 'success' => false,
40
+ 'message' => $this->__('Invalid session. Please try placing the order again.'),
41
+ ), 400);
42
+ }
43
+
44
+ // Check post parameters
45
+ $phoneNumber = $this->getRequest()->getParam('phone_number');
46
+
47
+ if(!$phoneNumber) {
48
+ $helper->getLogger()->err('Called charge_user action with no phone number');
49
+ $helper->getLogger()->err($session->getData());
50
+
51
+ return $this->renderAjaxResponse(array(
52
+ 'success' => false,
53
+ 'message' => $this->__('Phone number is a required field'),
54
+ ), 400);
55
+ }
56
+
57
+ $helper->getLogger()->info('Called charge_user action with phone number: ' . $phoneNumber);
58
+ $helper->getLogger()->info($session->getData());
59
+
60
+ // Process request
61
+ $client = $helper->getClient();
62
+ $user = $client->userCreate($phoneNumber);
63
+
64
+ // Check user creation response
65
+ if(!isset($user->id)) {
66
+
67
+ $helper->getLogger()->err('Error in user creation');
68
+ $helper->getLogger()->err($user);
69
+
70
+ return $this->renderAjaxResponse(array(
71
+ 'success' => false,
72
+ 'message' => $user->message,
73
+ ), 400);
74
+ }
75
+
76
+ // Create charge
77
+ $charge = $client->chargeCreate(
78
+ $session->getOrderId(),
79
+ $user->id,
80
+ $session->getCurrency(),
81
+ $session->getAmount()
82
+ );
83
+
84
+ // Check user creation response
85
+ if(!isset($charge->id)) {
86
+
87
+ $helper->getLogger()->err('Error in charge request creation');
88
+ $helper->getLogger()->err($charge);
89
+
90
+ return $this->renderAjaxResponse(array(
91
+ 'success' => false,
92
+ 'message' => $charge->message,
93
+ ), 400);
94
+ }
95
+
96
+ $helper->getLogger()->info('Charge request created');
97
+ $helper->getLogger()->info($charge);
98
+
99
+ // Update session
100
+ $session->setChargeId($charge->id);
101
+
102
+ // Update order payment informations
103
+ $order = Mage::getModel('sales/order')
104
+ ->load($session->getOrderId(), 'increment_id');
105
+
106
+ $order->getPayment()
107
+ ->setLastTransId($charge->id)
108
+ ->save();
109
+
110
+ return $this->renderAjaxResponse(array(
111
+ 'success' => true,
112
+ ));
113
+ }
114
+
115
+ /**
116
+ * Check payment status
117
+ */
118
+ public function check_statusAction() {
119
+ $helper = Mage::helper('satispay');
120
+ $session = Mage::getSingleton('satispay/session');
121
+
122
+ // Check session parameters
123
+ if(!$session->getChargeId()) {
124
+ $helper->getLogger()->err('Called check_status action with invalid session');
125
+ $helper->getLogger()->err($session->getData());
126
+
127
+ return;
128
+ }
129
+
130
+ $helper->getLogger()->info('Called check_status action');
131
+ $helper->getLogger()->info($session->getData());
132
+
133
+ // Load order
134
+ $order = Mage::getModel('sales/order')
135
+ ->load($session->getOrderId(), 'increment_id');
136
+
137
+ // If payment is still pending, check the charge request for updates
138
+ if($order->getStatus() == Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) {
139
+ try {
140
+ Mage::helper('satispay/order')
141
+ ->update($order, $session->getChargeId());
142
+ } catch(Exception $ex) {
143
+ $helper->getLogger()->err('Error in order update: ' . $ex->getMessage());
144
+
145
+ return $this->renderAjaxResponse(array(
146
+ 'redirect' => Mage::getUrl('/'),
147
+ ), 500);
148
+ }
149
+ }
150
+
151
+ // Payment is still pending
152
+ if($order->getStatus() == Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) {
153
+ return $this->renderAjaxResponse(array(
154
+ 'pending' => true,
155
+ ));
156
+ } elseif($order->getStatus() == Mage_Sales_Model_Order::STATE_CANCELED) {
157
+ $session->clear();
158
+
159
+ return $this->renderAjaxResponse(array(
160
+ 'redirect' => Mage::getUrl('checkout/onepage/failure'),
161
+ ));
162
+ } else {
163
+ $session->clear();
164
+
165
+ return $this->renderAjaxResponse(array(
166
+ 'redirect' => Mage::getUrl('checkout/onepage/success'),
167
+ ));
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Render response object
173
+ */
174
+ protected function renderAjaxResponse($response, $statusCode=200) {
175
+ $this->getResponse()
176
+ ->setHeader('HTTP/1.0', $statusCode, true)
177
+ ->setHeader('Content-Type', 'application/json')
178
+ ->setBody(Mage::helper('core')->jsonEncode($response));
179
+ }
180
+ }
app/code/community/Bitbull/Satispay/etc/config.xml ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Bitbull_Satispay>
5
+ <version>0.2.0</version>
6
+ </Bitbull_Satispay>
7
+ </modules>
8
+ <global>
9
+ <blocks>
10
+ <satispay>
11
+ <class>Bitbull_Satispay_Block</class>
12
+ </satispay>
13
+ </blocks>
14
+ <helpers>
15
+ <satispay>
16
+ <class>Bitbull_Satispay_Helper</class>
17
+ </satispay>
18
+ </helpers>
19
+ <models>
20
+ <satispay>
21
+ <class>Bitbull_Satispay_Model</class>
22
+ </satispay>
23
+ </models>
24
+ </global>
25
+ <frontend>
26
+ <layout>
27
+ <updates>
28
+ <satispay>
29
+ <file>bitbull/satispay.xml</file>
30
+ </satispay>
31
+ </updates>
32
+ </layout>
33
+ <routers>
34
+ <satispay>
35
+ <use>standard</use>
36
+ <args>
37
+ <module>Bitbull_Satispay</module>
38
+ <frontName>satispay</frontName>
39
+ </args>
40
+ </satispay>
41
+ </routers>
42
+ <translate>
43
+ <modules>
44
+ <Bitbull_Satispay>
45
+ <files>
46
+ <default>Bitbull_Satispay.csv</default>
47
+ </files>
48
+ </Bitbull_Satispay>
49
+ </modules>
50
+ </translate>
51
+ </frontend>
52
+ <adminhtml>
53
+ <translate>
54
+ <modules>
55
+ <Bitbull_Satispay>
56
+ <files>
57
+ <default>Bitbull_Satispay.csv</default>
58
+ </files>
59
+ </Bitbull_Satispay>
60
+ </modules>
61
+ </translate>
62
+ </adminhtml>
63
+ <crontab>
64
+ <jobs>
65
+ <satispay_process_pendingorders>
66
+ <schedule><cron_expr>*/10 * * * *</cron_expr></schedule>
67
+ <run><model>satispay/cron::processPendingOrders</model></run>
68
+ </satispay_process_pendingorders>
69
+ </jobs>
70
+ </crontab>
71
+ <default>
72
+ <payment>
73
+ <satispay>
74
+ <title>Pay with Satispay</title>
75
+ <order_status>pending_payment</order_status>
76
+ <payment_action>sale</payment_action>
77
+ <model>satispay/payment</model>
78
+ <default_country_code>+39</default_country_code>
79
+ </satispay>
80
+ </payment>
81
+ </default>
82
+ </config>
app/code/community/Bitbull/Satispay/etc/system.xml ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <sections>
4
+ <payment>
5
+ <groups>
6
+ <satispay translate="label">
7
+ <label>Bitbull Satispay Itegration</label>
8
+ <frontend_type>text</frontend_type>
9
+ <sort_order>999</sort_order>
10
+ <show_in_default>1</show_in_default>
11
+ <show_in_website>1</show_in_website>
12
+ <show_in_store>1</show_in_store>
13
+ <fields>
14
+ <active translate="label">
15
+ <label>Enabled</label>
16
+ <frontend_type>select</frontend_type>
17
+ <source_model>adminhtml/system_config_source_yesno</source_model>
18
+ <sort_order>1</sort_order>
19
+ <show_in_default>1</show_in_default>
20
+ <show_in_website>1</show_in_website>
21
+ <show_in_store>0</show_in_store>
22
+ </active>
23
+ <title translate="label">
24
+ <label>Title</label>
25
+ <frontend_type>text</frontend_type>
26
+ <sort_order>2</sort_order>
27
+ <show_in_default>1</show_in_default>
28
+ <show_in_website>1</show_in_website>
29
+ <show_in_store>0</show_in_store>
30
+ </title>
31
+ <instructions translate="label">
32
+ <label>Instructions</label>
33
+ <frontend_type>textarea</frontend_type>
34
+ <sort_order>3</sort_order>
35
+ <show_in_default>1</show_in_default>
36
+ <show_in_website>1</show_in_website>
37
+ <show_in_store>0</show_in_store>
38
+ </instructions>
39
+ <staging translate="label">
40
+ <label>Staging Mode</label>
41
+ <frontend_type>select</frontend_type>
42
+ <source_model>adminhtml/system_config_source_yesno</source_model>
43
+ <sort_order>4</sort_order>
44
+ <show_in_default>1</show_in_default>
45
+ <show_in_website>1</show_in_website>
46
+ <show_in_store>0</show_in_store>
47
+ </staging>
48
+ <security_token translate="label">
49
+ <label>Security Token</label>
50
+ <frontend_type>textarea</frontend_type>
51
+ <sort_order>5</sort_order>
52
+ <show_in_default>1</show_in_default>
53
+ <show_in_website>1</show_in_website>
54
+ <show_in_store>0</show_in_store>
55
+ </security_token>
56
+ <default_country_code translate="label">
57
+ <label>Default Country Code</label>
58
+ <frontend_type>select</frontend_type>
59
+ <source_model>satispay/system_config_source_countrycode</source_model>
60
+ <sort_order>6</sort_order>
61
+ <show_in_default>1</show_in_default>
62
+ <show_in_website>1</show_in_website>
63
+ <show_in_store>0</show_in_store>
64
+ </default_country_code>
65
+ <debug translate="label comment">
66
+ <label>Debug</label>
67
+ <comment>Force log messages regardless of system log settings</comment>
68
+ <frontend_type>select</frontend_type>
69
+ <source_model>adminhtml/system_config_source_yesno</source_model>
70
+ <sort_order>110</sort_order>
71
+ <show_in_default>1</show_in_default>
72
+ <show_in_website>1</show_in_website>
73
+ <show_in_store>0</show_in_store>
74
+ <depends><active>1</active></depends>
75
+ </debug>
76
+ </fields>
77
+ </satispay>
78
+ </groups>
79
+ </payment>
80
+ </sections>
81
+ </config>
app/design/adminhtml/base/default/template/bitbull/satispay/payment/info.phtml ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php if($this->getInfo() && ($transactionId = $this->getInfo()->getLastTransId())): ?>
2
+ <?php echo $this->__('Transaction ID: %s', $transactionId) ?>
3
+ <?php endif; ?>
app/design/frontend/base/default/layout/bitbull/satispay.xml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+ <satispay_payment_index translate="label">
4
+ <label>Satispay Payment Page</label>
5
+ <remove name="right"/>
6
+ <remove name="left"/>
7
+
8
+ <reference name="root">
9
+ <action method="setTemplate"><template>page/1column.phtml</template></action>
10
+ </reference>
11
+ <reference name="head">
12
+ <action method="addItem"><type>skin_css</type><file>bitbull/satispay/css/payment.css</file></action>
13
+ <action method="addItem"><type>skin_js</type><file>bitbull/satispay/js/payment.js</file></action>
14
+ </reference>
15
+ <reference name="content">
16
+ <block type="satispay/payment_page" name="satispay.payment.page" template="bitbull/satispay/payment/page.phtml" />
17
+ </reference>
18
+ </satispay_payment_index>
19
+ </layout>
app/design/frontend/base/default/template/bitbull/satispay/payment/form.phtml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php if ($instructions = $this->getInstructions()): ?>
2
+ <ul class="form-list" id="payment_form_<?php echo $this->getMethodCode() ?>" style="display:none;">
3
+ <li>
4
+ <div class="<?php echo $this->getMethodCode() ?>-instructions-content">
5
+ <?php echo nl2br($instructions) ?>
6
+ </div>
7
+ </li>
8
+ </ul>
9
+ <?php endif; ?>
app/design/frontend/base/default/template/bitbull/satispay/payment/info.phtml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php echo $this->getTitle() ?>
2
+ <?php if($this->getInfo() && ($transactionId = $this->getInfo()->getLastTransId())): ?>
3
+ <br />
4
+ <?php echo $this->__('Transaction ID: %s', $transactionId) ?>
5
+ <?php endif; ?>
app/design/frontend/base/default/template/bitbull/satispay/payment/page.phtml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $defaultCountryCode = $this->getDefaultCountryCode(); ?>
2
+ <?php $countryCodes = $this->getCountryCodes(); ?>
3
+ <div class="satispay-container">
4
+ <img class="satispay-logo" src="<?php echo $this->getSkinUrl('bitbull/satispay/images/satispay_logo.png') ?>" alt="<?php echo $this->__('Satispay') ?>" />
5
+ <p class="instructions"><?php echo $this->__('Please enter the Satispay number you want to charge for the order.') ?></p>
6
+ <div class="phone-selection">
7
+ <select id="country-code">
8
+ <?php foreach($countryCodes as $countryCode): ?>
9
+ <option <?php if($countryCode == $defaultCountryCode) echo 'selected="selected"' ?>><?php echo $countryCode ?></option>
10
+ <?php endforeach; ?>
11
+ </select>
12
+ <input type="text" id="phone-number" value="<?php echo $this->escapeHtml($this->getPhoneNumber()) ?>" />
13
+ </div>
14
+ <div class="errors" style="display:none"></div>
15
+ <div class="success" style="display:none">
16
+ <?php echo $this->__('Request successfully sent. Please confirm the payment from the mobile Satispay application.') ?>
17
+ </div>
18
+ <input type="submit" id="submit" value="<?php echo $this->__('Send Request') ?>" />
19
+ </div>
20
+
21
+ <script type="text/javascript">
22
+ var satispay = new Satispay_Payment(<?php echo Mage::helper('core')->jsonEncode(array(
23
+ 'chargeEndpoint' => Mage::getUrl('satispay/payment/charge_user', array('_secure'=>true)),
24
+ 'statusEndpoint' => Mage::getUrl('satispay/payment/check_status', array('_secure'=>true)),
25
+ )); ?>);
26
+ </script>
app/etc/modules/Bitbull_Satispay.xml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Bitbull_Satispay>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends></depends>
8
+ </Bitbull_Satispay>
9
+ </modules>
10
+ </config>
app/locale/en_US/Bitbull_Satispay.csv ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ "Transaction ID: %s","Transaction ID: %s"
2
+ "Please enter the Satispay number you want to charge for the order.","Please enter the Satispay number you want to charge for the order."
3
+ "Send Request","Send Request"
4
+ "Invalid session. Please try placing the order again.","Invalid session. Please try placing the order again."
5
+ "Phone number is a required field","Phone number is a required field"
6
+ "Request successfully sent. Please confirm the payment from the mobile Satispay application.","Request successfully sent. Please confirm the payment from the mobile Satispay application."
app/locale/it_IT/Bitbull_Satispay.csv ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ "Transaction ID: %s","ID Transazione: %s"
2
+ "Please enter the Satispay number you want to charge for the order.","Inserisci il numero Satispay per inviare una richiesta di addebito."
3
+ "Send Request","Invia Richiesta"
4
+ "Invalid session. Please try placing the order again.","Sessione scaduta. Ripetere l'ordine."
5
+ "Phone number is a required field","Il numero di telefono è un campo richiesto"
6
+ "Request successfully sent. Please confirm the payment from the mobile Satispay application.","Richiesta inviata con successo. Utilizzare l'app Satispay per confermare il pagamento."
lib/Satispay/Core/.gitkeep ADDED
File without changes
lib/Satispay/Core/Client.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Satispay APIs v1.0 Client
5
+ */
6
+ class Satispay_Core_Client {
7
+ const HTTP_TIMEOUT = 60;
8
+
9
+ const PRODUCTION_ENDPOINT = 'authservices.satispay.com';
10
+ const STAGING_ENDPOINT = 'staging.authservices.satispay.com';
11
+ const STAGING_SECURITY_TOKEN = 'osh_cgml4ekip198n22sef1f05kfa389j9pqnll6hg5nq05ppla1f3b1eitv73o53mqhjdujq4m5kgc0fa0f5nojvisrqmunbk14dutt1qi95qgfstb60glek063beftbmc12htftpkjvchtckj7fi9ep5c56l9d356ev30tlrfubvfiugo44lomgac0hd9rpbf326lsmj06';
12
+
13
+ const PAYMENT_STATUS_REQUESTED = 'REQUESTED';
14
+ const PAYMENT_STATUS_SUCCEESS = 'SUCCESS';
15
+ const PAYMENT_STATUS_DECLINED = 'DECLINED';
16
+ const PAYMENT_STATUS_FAILURE = 'FAILURE';
17
+
18
+ protected $_staging;
19
+ protected $_security_token;
20
+
21
+ public function setStaging($value) {
22
+ $this->_staging = $value;
23
+ return $this;
24
+ }
25
+
26
+ public function setSecurityToken($value) {
27
+ $this->_security_token = $value;
28
+ return $this;
29
+ }
30
+
31
+ /**
32
+ * Get API endpoint
33
+ */
34
+ protected function getEndpoint() {
35
+ return $this->_staging ? self::STAGING_ENDPOINT : self::PRODUCTION_ENDPOINT;
36
+ }
37
+
38
+ /**
39
+ * Get security token for bearer authentication
40
+ */
41
+ protected function getSecurityToken() {
42
+ return $this->_staging ? self::STAGING_SECURITY_TOKEN : $this->_security_token;
43
+ }
44
+
45
+ /**
46
+ * Make an API call to the specified resource
47
+ *
48
+ * @param string $idempotencyKey Request unique value, to avoid duplication
49
+ * @param string $resource API resource
50
+ * @param array $params POST request parameters (optional)
51
+ */
52
+ private function getResponse($idempotencyKey, $resource, $params=array()) {
53
+ $h = curl_init();
54
+
55
+ // Initialize request
56
+ curl_setopt($h, CURLOPT_URL, 'https://' . $this->getEndpoint() . $resource);
57
+ curl_setopt($h, CURLOPT_RETURNTRANSFER, 1);
58
+ curl_setopt($h, CURLOPT_CONNECTTIMEOUT, self::HTTP_TIMEOUT);
59
+ curl_setopt($h, CURLOPT_TIMEOUT, self::HTTP_TIMEOUT);
60
+
61
+ // Ignore certificate issues in staging
62
+ if($this->_staging) {
63
+ curl_setopt($h, CURLOPT_SSL_VERIFYHOST, false);
64
+ curl_setopt($h, CURLOPT_SSL_VERIFYPEER, false);
65
+ }
66
+
67
+ // Add headers
68
+ $headers = array(
69
+ 'Content-type: application/json',
70
+ 'Authorization: Bearer ' . $this->getSecurityToken(),
71
+ );
72
+ curl_setopt($h, CURLOPT_HTTPHEADER, $headers);
73
+
74
+ // Add parameter (if post request)
75
+ if($params) {
76
+ curl_setopt($h, CURLOPT_POST, 1);
77
+ curl_setopt($h, CURLOPT_POSTFIELDS, json_encode($params));
78
+ }
79
+
80
+ $content = curl_exec($h);
81
+ curl_close($h);
82
+
83
+ return json_decode($content);
84
+ }
85
+
86
+ /**
87
+ * Create a new user
88
+ *
89
+ * @param string $phoneNumber The user's phone number
90
+ */
91
+ public function userCreate($phoneNumber) {
92
+ // Idempotency key is not important in this request, as
93
+ // multiple calls with the same number returns the same id
94
+ $idempotencyKey = microtime(true);
95
+
96
+ // Make request
97
+ return $this->getResponse($idempotencyKey, '/online/v1/users', array(
98
+ 'phone_number' => $phoneNumber,
99
+ ));
100
+ }
101
+
102
+ /**
103
+ * Create charge request
104
+ * @param string $orderId
105
+ * @param string $userId
106
+ * @param string $currency
107
+ * @param float $amount
108
+ */
109
+ public function chargeCreate($orderId, $userId, $currency, $amount) {
110
+ // Using order id as idempotency key, in order to avoid multiple charges for same order
111
+ return $this->getResponse($orderId, '/online/v1/charges', array(
112
+ 'user_id' => $userId,
113
+ 'order_id' => $orderId,
114
+ 'currency' => $currency,
115
+ 'amount' => $amount,
116
+ ));
117
+ }
118
+
119
+ /**
120
+ * Get charge informations
121
+ * @param string $id
122
+ */
123
+ public function chargeGet($id) {
124
+ // Idempotency key is not important in this request
125
+ $idempotencyKey = microtime(true);
126
+
127
+ // Make request
128
+ return $this->getResponse($idempotencyKey, '/online/v1/charges/' . $id);
129
+ }
130
+
131
+ /**
132
+ * Create refund request
133
+ * @param string $chargeId
134
+ * @param string $currency
135
+ * @param float $amount
136
+ */
137
+ public function refundCreate($chargeId, $currency, $amount) {
138
+ $idempotencyKey = microtime(true);
139
+
140
+ return $this->getResponse($idempotencyKey, '/online/v1/refunds', array(
141
+ 'charge_id' => $chargeId,
142
+ 'currency' => $currency,
143
+ 'amount' => $amount,
144
+ ));
145
+ }
146
+ }
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Bitbull_Satispay</name>
4
+ <version>0.2.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="https://opensource.org/licenses/OSL-3.0">Open Software License (OSL)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Satispay payment gateway for Magento 1.9.x</summary>
10
+ <description>Bitbull_Satispay extension enables your shop to receive payments using Satispay.</description>
11
+ <notes>First stable version.</notes>
12
+ <authors><author><name>Renato Cason</name><user>bitbull_team</user><email>devel@bitbull.it</email></author></authors>
13
+ <date>2016-05-20</date>
14
+ <time>14:43:47</time>
15
+ <contents><target name="mageetc"><dir name="modules"><file name="Bitbull_Satispay.xml" hash="e29f9792ca510be121a0bf867aba8b40"/></dir></target><target name="magelib"><dir name="Satispay"><dir name="Core"><file name="Client.php" hash="9ad0aae9447343657edba256e157defa"/><file name=".gitkeep" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir></dir></target><target name="magecommunity"><dir name="Bitbull"><dir name="Satispay"><dir name="Block"><dir name="Payment"><file name="Form.php" hash="2a92ec1fd664fb537d7e12dd4bfb9a97"/><file name="Info.php" hash="582388609b22ba68b10b6fa5270187f9"/><file name="Page.php" hash="7c53d1f85d97db5da3e6b9353004cbfe"/></dir></dir><dir name="Helper"><file name="Data.php" hash="c73362f14dd81f792e968950e5a78a6b"/><file name="Order.php" hash="65e4ef408b2016baca2f0c8db03d40fb"/><file name="Phone.php" hash="1d25accc1311e8be5f608a965110b061"/></dir><dir name="Model"><file name="Cron.php" hash="9a60dd5021b58e3f48bbba6e90a9932b"/><file name="Logger.php" hash="73e12d969afa8a7600f785f28b2abed5"/><file name="Payment.php" hash="d2960416aa7b447da009a88f878089ce"/><file name="Session.php" hash="38ff5005a5ad78a1450b758645209cad"/><dir name="System"><dir name="Config"><dir name="Source"><file name="Countrycode.php" hash="caf42dc3e24629116edb930581b5cfc4"/></dir></dir></dir></dir><dir name="controllers"><file name="PaymentController.php" hash="c47762a35d9cb85c9dde345974fb737a"/></dir><dir name="etc"><file name="config.xml" hash="1c4e145ddd7d0455eadc8e36552a6c78"/><file name="system.xml" hash="254b7329e384f94cffe058c7bcc78c91"/></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><dir name="bitbull"><file name="satispay.xml" hash="ecb54fc1f2606a24007f04b7ec3f2f92"/></dir></dir><dir name="template"><dir name="bitbull"><dir name="satispay"><dir><dir name="payment"><file name="form.phtml" hash="936fdfd76081c6382c4fd18eda40fb39"/><file name="info.phtml" hash="da0eece5659d73746c1f7e0a7d593b7f"/><file name="page.phtml" hash="486e56e8292d58d7b05b8e7c6502e3fe"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="template"><dir name="bitbull"><dir name="satispay"><dir name="payment"><file name="info.phtml" hash="2c90d6f0e8cdd838e5fa7e5a340e92db"/></dir></dir></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="bitbull"><dir name="satispay"><dir name="css"><file name="payment.css" hash="8a63a861687a7670e932ac56f2218a11"/></dir><dir name="images"><file name="satispay_logo.png" hash="23dcf008e223b93536b4f2f3f731602f"/></dir><dir name="js"><file name="payment.js" hash="f2efafd7072de4d9414b778f8a32f4ec"/></dir></dir></dir></dir></dir></dir></target><target name="magelocale"><dir><dir name="en_US"><file name="Bitbull_Satispay.csv" hash="6783cb58763d4861c992c7e213bb75c0"/></dir><dir name="it_IT"><file name="Bitbull_Satispay.csv" hash="fbb1585eb56e724a33bc99b7d085a41e"/></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.5.0</min><max>7.0.6</max></php></required></dependencies>
18
+ </package>
skin/frontend/base/default/bitbull/satispay/css/payment.css ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .satispay-container {
2
+ background-color: #F7F7F7;
3
+ border-radius: 5px;
4
+ width: 100%;
5
+ max-width: 400px;
6
+ margin: 0 auto;
7
+ padding: 15px;
8
+ text-align: center;
9
+ }
10
+
11
+ .satispay-container .satispay-logo {
12
+ margin: 0 auto;
13
+ padding: 10px;
14
+ }
15
+
16
+ .satispay-container .phone-selection select {
17
+ position: absolute;
18
+ width: 5%;
19
+ height: 30px;
20
+ border: 1px solid black;
21
+ }
22
+
23
+ .satispay-container .phone-selection input {
24
+ width: 82%;
25
+ margin-left: 18%;
26
+ }
27
+
28
+ .satispay-container .errors {
29
+ color: #F94C43;
30
+ font-weight: bold;
31
+ padding: 15px;
32
+ }
33
+ .satispay-container .success {
34
+ font-weight: bold;
35
+ padding: 15px;
36
+ }
37
+
38
+ .satispay-container #submit {
39
+ border: 0px solid #F94C43;
40
+ background-color: #F94C43;
41
+ padding: 10px;
42
+ margin: 10px;
43
+ color: white;
44
+ }
skin/frontend/base/default/bitbull/satispay/images/satispay_logo.png ADDED
Binary file
skin/frontend/base/default/bitbull/satispay/js/payment.js ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var Satispay_Payment = function(options) {
2
+ var self = this;
3
+ var interval = 4000;
4
+
5
+ this.renderError = function(message) {
6
+ jQuery('.satispay-container .errors').html(message).fadeIn();
7
+ };
8
+ this.hideError = function() {
9
+ jQuery('.satispay-container .errors').fadeOut();
10
+ };
11
+ this.renderSuccess = function() {
12
+ jQuery('.satispay-container .instructions, .satispay-container .phone-selection, .satispay-container #submit').fadeOut(function() {
13
+ jQuery('.satispay-container .success').fadeIn();
14
+ });
15
+ };
16
+
17
+ this.checkStatus = function() {
18
+ jQuery.get(options.statusEndpoint, function(data) {
19
+ if(!data.pending && data.redirect) {
20
+ location.href = data.redirect;
21
+ return;
22
+ }
23
+
24
+ setTimeout(self.checkStatus, interval);
25
+ });
26
+ };
27
+
28
+ this.submit = function() {
29
+ self.hideError();
30
+ var phoneNumber = jQuery('#country-code').val() + jQuery('#phone-number').val();
31
+ jQuery.post(options.chargeEndpoint, { phone_number: phoneNumber }, function(data) {
32
+ if(!data.success) {
33
+ self.renderError(data.message);
34
+ return;
35
+ }
36
+
37
+ self.renderSuccess();
38
+ setTimeout(self.checkStatus, interval);
39
+ }).fail(function(response) {
40
+ if(!response.responseJSON.message) {
41
+ return;
42
+ }
43
+
44
+ self.renderError(response.responseJSON.message);
45
+ });
46
+ };
47
+
48
+ jQuery('#submit').click(this.submit);
49
+ jQuery('#phone-number').keypress(function(e) {
50
+ if(e.keyCode == 13) {
51
+ self.submit();
52
+ }
53
+ });
54
+ }