kash_gateway - Version 0.1.1

Version Notes

v0.1.1 - Initial Release

Download this release

Release Info

Developer Kash Corp.
Extension kash_gateway
Version 0.1.1
Comparing to
See all releases


Version 0.1.1

Files changed (33) hide show
  1. app/code/local/Kash/Gateway/Block/Adminhtml/Info.php +24 -0
  2. app/code/local/Kash/Gateway/Block/Adminhtml/Sales/Order/Grid.php +24 -0
  3. app/code/local/Kash/Gateway/Block/Form/Bb.php +63 -0
  4. app/code/local/Kash/Gateway/Block/Review.php +185 -0
  5. app/code/local/Kash/Gateway/Block/Review/Details.php +31 -0
  6. app/code/local/Kash/Gateway/Helper/Checkout.php +67 -0
  7. app/code/local/Kash/Gateway/Helper/Data.php +10 -0
  8. app/code/local/Kash/Gateway/Model/Api/Abstract.php +357 -0
  9. app/code/local/Kash/Gateway/Model/Api/Bb.php +235 -0
  10. app/code/local/Kash/Gateway/Model/Cart.php +497 -0
  11. app/code/local/Kash/Gateway/Model/Checkout.php +655 -0
  12. app/code/local/Kash/Gateway/Model/Config.php +183 -0
  13. app/code/local/Kash/Gateway/Model/Method/Bb.php +111 -0
  14. app/code/local/Kash/Gateway/Model/Observer.php +68 -0
  15. app/code/local/Kash/Gateway/Model/Session.php +11 -0
  16. app/code/local/Kash/Gateway/controllers/BbController.php +448 -0
  17. app/code/local/Kash/Gateway/data/kash_gateway_setup/data-install-0.0.1.php +10 -0
  18. app/code/local/Kash/Gateway/data/kash_gateway_setup/data-upgrade-0.0.1-0.0.2.php +40 -0
  19. app/code/local/Kash/Gateway/etc/config.xml +119 -0
  20. app/code/local/Kash/Gateway/etc/system.xml +114 -0
  21. app/code/local/Kash/Gateway/sql/kash_gateway_setup/install-0.0.1.php +22 -0
  22. app/design/adminhtml/default/default/template/kash/info/default.phtml +30 -0
  23. app/design/frontend/base/default/layout/kash/gateway.xml +72 -0
  24. app/design/frontend/base/default/template/kash/container.phtml +5 -0
  25. app/design/frontend/base/default/template/kash/form.phtml +13 -0
  26. app/design/frontend/base/default/template/kash/js.phtml +56 -0
  27. app/design/frontend/base/default/template/kash/payment/mark.phtml +7 -0
  28. app/design/frontend/base/default/template/kash/payment/redirect.phtml +8 -0
  29. app/design/frontend/base/default/template/kash/payment/review.phtml +65 -0
  30. app/design/frontend/base/default/template/kash/payment/review/details.phtml +39 -0
  31. app/etc/modules/Kash_Gateway.xml +12 -0
  32. package.xml +22 -0
  33. skin/frontend/base/default/css/kash/start.css +3 -0
app/code/local/Kash/Gateway/Block/Adminhtml/Info.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base payment iformation block
4
+ *
5
+ */
6
+ class Kash_Gateway_Block_Adminhtml_Info extends Mage_Payment_Block_Info
7
+ {
8
+ /**
9
+ * Payment rendered specific information
10
+ *
11
+ * @var Varien_Object
12
+ */
13
+ protected $_paymentSpecificInformation = null;
14
+
15
+ protected function _construct()
16
+ {
17
+ parent::_construct();
18
+ $this->setTemplate('kash/info/default.phtml');
19
+ }
20
+
21
+ public function getAdditionalInformation(){
22
+ return $this->getInfo()->getAdditionalInformation();
23
+ }
24
+ }
app/code/local/Kash/Gateway/Block/Adminhtml/Sales/Order/Grid.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Kash_Gateway_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid {
4
+
5
+ protected function _prepareCollection()
6
+ {
7
+ $collection = Mage::getResourceModel($this->_getCollectionClass());
8
+
9
+ $collection->join('sales/order_payment', '`main_table`.entity_id=`sales/order_payment`.entity_id', array('x_gateway_reference' =>'x_gateway_reference'), null,'left');
10
+ $this->setCollection($collection);
11
+ return Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();
12
+ }
13
+
14
+ protected function _prepareColumns()
15
+ {
16
+ parent::_prepareColumns();
17
+ $this->addColumnAfter('x_gateway_reference', array(
18
+ 'header' => Mage::helper('catalog')->__('Gateway Reference'),
19
+ 'index' => 'x_gateway_reference',
20
+ 'type' => 'text'
21
+ ),'sku');
22
+ }
23
+
24
+ }
app/code/local/Kash/Gateway/Block/Form/Bb.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Payment BB "form"
5
+ *
6
+ * @author Blue Badger <jonathan@badger.blue>
7
+ */
8
+ class Kash_Gateway_Block_Form_Bb extends Mage_Payment_Block_Form
9
+ {
10
+ /**
11
+ * Payment method code
12
+ * @var string
13
+ */
14
+ protected $_methodCode = Kash_Gateway_Model_Config::METHOD_GATEWAY_KASH;
15
+
16
+ /**
17
+ * Config model instance
18
+ *
19
+ * @var Kash_Gateway_Model_Config
20
+ */
21
+ protected $_config;
22
+
23
+ /**
24
+ * Set template and redirect message
25
+ */
26
+ protected function _construct()
27
+ {
28
+ $this->_config = Mage::getModel('kash_gateway/config')->setMethod($this->getMethodCode());
29
+ $locale = Mage::app()->getLocale();
30
+ $mark = Mage::getConfig()->getBlockClassName('core/template');
31
+ $mark = new $mark;
32
+ $mark->setTemplate('kash/payment/mark.phtml')
33
+ ->setPaymentImageSrc($this->_config->getPaymentImageUrl($locale->getLocaleCode()))
34
+ ->setMessage(
35
+ Mage::helper('kash_gateway')->__($this->_config->title)
36
+ );
37
+ $this->setTemplate('kash/payment/redirect.phtml')
38
+ ->setRedirectMessage(
39
+ Mage::helper('kash_gateway')->__('')
40
+ )
41
+ ->setMethodTitle('')
42
+ ->setMethodLabelAfterHtml($mark->toHtml())
43
+ ;
44
+ $result = parent::_construct();
45
+ return $result;
46
+ }
47
+
48
+ /**
49
+ * Set data to block
50
+ *
51
+ * @return Mage_Core_Block_Abstract
52
+ */
53
+ protected function _beforeToHtml()
54
+ {
55
+ $customerId = Mage::getSingleton('customer/session')->getCustomerId();
56
+ return parent::_beforeToHtml();
57
+ }
58
+
59
+ public function getMethodCode()
60
+ {
61
+ return $this->_methodCode;
62
+ }
63
+ }
app/code/local/Kash/Gateway/Block/Review.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Payment Onepage checkout block
4
+ */
5
+ class Kash_Gateway_Block_Review extends Mage_Core_Block_Template
6
+ {
7
+ /**
8
+ * @var Mage_Sales_Model_Quote
9
+ */
10
+ protected $_quote;
11
+
12
+ /**
13
+ * Currently selected shipping rate
14
+ *
15
+ * @var Mage_Sales_Model_Quote_Address_Rate
16
+ */
17
+ protected $_currentShippingRate = null;
18
+
19
+ /**
20
+ * Quote object setter
21
+ *
22
+ * @param Mage_Sales_Model_Quote $quote
23
+ * @return $this
24
+ */
25
+ public function setQuote(Mage_Sales_Model_Quote $quote)
26
+ {
27
+ $this->_quote = $quote;
28
+ return $this;
29
+ }
30
+
31
+ /**
32
+ * Return quote billing address
33
+ *
34
+ * @return Mage_Sales_Model_Quote_Address
35
+ */
36
+ public function getBillingAddress()
37
+ {
38
+ return $this->_quote->getBillingAddress();
39
+ }
40
+
41
+ /**
42
+ * Return quote shipping address
43
+ *
44
+ * @return Mage_Sales_Model_Quote_Address
45
+ */
46
+ public function getShippingAddress()
47
+ {
48
+ if ($this->_quote->getIsVirtual()) {
49
+ return false;
50
+ }
51
+ return $this->_quote->getShippingAddress();
52
+ }
53
+
54
+ /**
55
+ * Get HTML output for specified address
56
+ *
57
+ * @param Mage_Sales_Model_Quote_Address
58
+ * @return string
59
+ */
60
+ public function renderAddress($address)
61
+ {
62
+ return $address->getFormated(true);
63
+ }
64
+
65
+ /**
66
+ * Return carrier name from config, base on carrier code
67
+ *
68
+ * @param $carrierCode string
69
+ * @return string
70
+ */
71
+ public function getCarrierName($carrierCode)
72
+ {
73
+ if ($name = Mage::getStoreConfig("carriers/{$carrierCode}/title")) {
74
+ return $name;
75
+ }
76
+ return $carrierCode;
77
+ }
78
+
79
+ /**
80
+ * Get either shipping rate code or empty value on error
81
+ *
82
+ * @param Varien_Object $rate
83
+ * @return string
84
+ */
85
+ public function renderShippingRateValue(Varien_Object $rate)
86
+ {
87
+ if ($rate->getErrorMessage()) {
88
+ return '';
89
+ }
90
+ return $rate->getCode();
91
+ }
92
+
93
+ /**
94
+ * Get shipping rate code title and its price or error message
95
+ *
96
+ * @param Varien_Object $rate
97
+ * @param string $format
98
+ * @param string $inclTaxFormat
99
+ * @return string
100
+ */
101
+ public function renderShippingRateOption($rate, $format = '%s - %s%s', $inclTaxFormat = ' (%s %s)')
102
+ {
103
+ $renderedInclTax = '';
104
+ if ($rate->getErrorMessage()) {
105
+ $price = $rate->getErrorMessage();
106
+ } else {
107
+ $price = $this->_getShippingPrice($rate->getPrice(),
108
+ $this->helper('tax')->displayShippingPriceIncludingTax());
109
+
110
+ $incl = $this->_getShippingPrice($rate->getPrice(), true);
111
+ if (($incl != $price) && $this->helper('tax')->displayShippingBothPrices()) {
112
+ $renderedInclTax = sprintf($inclTaxFormat, Mage::helper('tax')->__('Incl. Tax'), $incl);
113
+ }
114
+ }
115
+ return sprintf($format, $this->escapeHtml($rate->getMethodTitle()), $price, $renderedInclTax);
116
+ }
117
+
118
+ /**
119
+ * Getter for current shipping rate
120
+ *
121
+ * @return Mage_Sales_Model_Quote_Address_Rate
122
+ */
123
+ public function getCurrentShippingRate()
124
+ {
125
+ return $this->_currentShippingRate;
126
+ }
127
+
128
+ /**
129
+ * Return formatted shipping price
130
+ *
131
+ * @param float $price
132
+ * @param bool $isInclTax
133
+ *
134
+ * @return bool
135
+ */
136
+ protected function _getShippingPrice($price, $isInclTax)
137
+ {
138
+ return $this->_formatPrice($this->helper('tax')->getShippingPrice($price, $isInclTax, $this->_address));
139
+ }
140
+
141
+ /**
142
+ * Format price base on store convert price method
143
+ *
144
+ * @param float $price
145
+ * @return string
146
+ */
147
+ protected function _formatPrice($price)
148
+ {
149
+ return $this->_quote->getStore()->convertPrice($price, true);
150
+ }
151
+
152
+ /**
153
+ * Retrieve payment method and assign additional template values
154
+ *
155
+ * @return Kash_Gateway_Block_Review
156
+ */
157
+ protected function _beforeToHtml()
158
+ {
159
+ $methodInstance = $this->_quote->getPayment()->getMethodInstance();
160
+ $this->setPaymentMethodTitle($methodInstance->getTitle());
161
+
162
+ $this->setShippingRateRequired(true);
163
+ if ($this->_quote->getIsVirtual()) {
164
+ $this->setShippingRateRequired(false);
165
+ } else {
166
+ // prepare shipping rates
167
+ $this->_address = $this->_quote->getShippingAddress();
168
+ $groups = $this->_address->getGroupedAllShippingRates();
169
+ if ($groups && $this->_address) {
170
+ $this->setShippingRateGroups($groups);
171
+ // determine current selected code & name
172
+ foreach ($groups as $code => $rates) {
173
+ foreach ($rates as $rate) {
174
+ if ($this->_address->getShippingMethod() == $rate->getCode()) {
175
+ $this->_currentShippingRate = $rate;
176
+ break(2);
177
+ }
178
+ }
179
+ }
180
+ }
181
+ }
182
+
183
+ return parent::_beforeToHtml();
184
+ }
185
+ }
app/code/local/Kash/Gateway/Block/Review/Details.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Payment Onepage checkout block
4
+ */
5
+ class Kash_Gateway_Block_Review_Details extends Mage_Checkout_Block_Cart_Totals
6
+ {
7
+ protected $_address;
8
+
9
+ /**
10
+ * Return review shipping address
11
+ *
12
+ * @return Mage_Sales_Model_Order_Address
13
+ */
14
+ public function getAddress()
15
+ {
16
+ if (empty($this->_address)) {
17
+ $this->_address = $this->getQuote()->getShippingAddress();
18
+ }
19
+ return $this->_address;
20
+ }
21
+
22
+ /**
23
+ * Return review quote totals
24
+ *
25
+ * @return array
26
+ */
27
+ public function getTotals()
28
+ {
29
+ return $this->getQuote()->getTotals();
30
+ }
31
+ }
app/code/local/Kash/Gateway/Helper/Checkout.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Checkout helper
5
+ */
6
+ class Kash_Gateway_Helper_Checkout extends Mage_Core_Helper_Abstract
7
+ {
8
+ /**
9
+ * Restore last active quote based on checkout session
10
+ *
11
+ * @return bool True if quote restored successfully, false otherwise
12
+ */
13
+ public function restoreQuote()
14
+ {
15
+ $order = $this->_getCheckoutSession()->getLastRealOrder();
16
+ if ($order->getId()) {
17
+ $quote = $this->_getQuote($order->getQuoteId());
18
+ if ($quote->getId()) {
19
+ $quote->setIsActive(1)
20
+ ->setReservedOrderId(null)
21
+ ->save();
22
+ $this->_getCheckoutSession()
23
+ ->replaceQuote($quote)
24
+ ->unsLastRealOrderId();
25
+ return true;
26
+ }
27
+ }
28
+ return false;
29
+ }
30
+
31
+ /**
32
+ * Cancel last placed order with specified comment message
33
+ *
34
+ * @param string $comment Comment appended to order history
35
+ * @return bool True if order cancelled, false otherwise
36
+ */
37
+ public function cancelCurrentOrder($comment)
38
+ {
39
+ $order = $this->_getCheckoutSession()->getLastRealOrder();
40
+ if ($order->getId() && $order->getState() != Mage_Sales_Model_Order::STATE_CANCELED) {
41
+ $order->registerCancellation($comment)->save();
42
+ return true;
43
+ }
44
+ return false;
45
+ }
46
+
47
+ /**
48
+ * Return checkout session instance
49
+ *
50
+ * @return Mage_Checkout_Model_Session
51
+ */
52
+ protected function _getCheckoutSession()
53
+ {
54
+ return Mage::getSingleton('checkout/session');
55
+ }
56
+
57
+ /**
58
+ * Return sales quote instance for specified ID
59
+ *
60
+ * @param int $quoteId Quote identifier
61
+ * @return Mage_Sales_Model_Quote
62
+ */
63
+ protected function _getQuote($quoteId)
64
+ {
65
+ return Mage::getModel('sales/quote')->load($quoteId);
66
+ }
67
+ }
app/code/local/Kash/Gateway/Helper/Data.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Payment module base helper
5
+ *
6
+ * @author Blue Badger <jonathan@badger.blue>
7
+ */
8
+ class Kash_Gateway_Helper_Data extends Mage_Core_Helper_Abstract {
9
+
10
+ }
app/code/local/Kash/Gateway/Model/Api/Abstract.php ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Abstract class for Paypal API wrappers
4
+ */
5
+ abstract class Kash_Gateway_Model_Api_Abstract extends Varien_Object
6
+ {
7
+ /**
8
+ * Config instance
9
+ * @var Kash_Gateway_Model_Config
10
+ */
11
+ protected $_config = null;
12
+
13
+ /**
14
+ * Global private to public interface map
15
+ * @var array
16
+ */
17
+ protected $_globalMap = array();
18
+
19
+ /**
20
+ * Filter callbacks for exporting $this data to API call
21
+ *
22
+ * @var array
23
+ */
24
+ protected $_exportToRequestFilters = array();
25
+
26
+ /**
27
+ * Filter callbacks for importing API result to $this data
28
+ *
29
+ * @var array
30
+ */
31
+ protected $_importFromRequestFilters = array();
32
+
33
+ /**
34
+ * Line items export to request mapping settings
35
+ * @var array
36
+ */
37
+ protected $_lineItemExportItemsFormat = array();
38
+ protected $_lineItemExportItemsFilters = array();
39
+ protected $_lineItemTotalExportMap = array();
40
+
41
+ /**
42
+ * PayPal shopping cart instance
43
+ *
44
+ * @var Kash_Gateway_Model_Cart
45
+ */
46
+ protected $_cart = null;
47
+
48
+ /**
49
+ * Shipping options export to request mapping settings
50
+ * @var array
51
+ */
52
+ protected $_shippingOptionsExportItemsFormat = array();
53
+
54
+ /**
55
+ * Import $this public data to specified object or array
56
+ *
57
+ * @param array|Varien_Object $to
58
+ * @param array $publicMap
59
+ * @return array|Varien_Object
60
+ */
61
+ public function &import($to, array $publicMap = array())
62
+ {
63
+ return Varien_Object_Mapper::accumulateByMap(array($this, 'getDataUsingMethod'), $to, $publicMap);
64
+ }
65
+
66
+ /**
67
+ * Export $this public data from specified object or array
68
+ *
69
+ * @param array|Varien_Object $from
70
+ * @param array $publicMap
71
+ * @return Kash_Gateway_Model_Api_Abstract
72
+ */
73
+ public function export($from, array $publicMap = array())
74
+ {
75
+ Varien_Object_Mapper::accumulateByMap($from, array($this, 'setDataUsingMethod'), $publicMap);
76
+ return $this;
77
+ }
78
+
79
+ /**
80
+ * Set Payment cart instance
81
+ *
82
+ * @param Kash_Gateway_Model_Cart $cart
83
+ * @return Kash_Gateway_Model_Api_Abstract
84
+ */
85
+ public function setPaymentCart(Kash_Gateway_Model_Cart $cart)
86
+ {
87
+ $this->_cart = $cart;
88
+ return $this;
89
+ }
90
+
91
+ /**
92
+ * Config instance setter
93
+ * @param Kash_Gateway_Model_Config $config
94
+ * @return Kash_Gateway_Model_Api_Abstract
95
+ */
96
+ public function setConfigObject(Kash_Gateway_Model_Config $config)
97
+ {
98
+ $this->_config = $config;
99
+ return $this;
100
+ }
101
+
102
+ /**
103
+ * Current locale code getter
104
+ *
105
+ * @return string
106
+ */
107
+ public function getLocaleCode()
108
+ {
109
+ return Mage::app()->getLocale()->getLocaleCode();
110
+ }
111
+
112
+ /**
113
+ * Export $this public data to private request array
114
+ *
115
+ * @param array $privateRequestMap
116
+ * @param array $request
117
+ * @return array
118
+ */
119
+ protected function &_exportToRequest(array $privateRequestMap, array $request = array())
120
+ {
121
+ $map = array();
122
+ foreach ($privateRequestMap as $key) {
123
+ if (isset($this->_globalMap[$key])) {
124
+ $map[$this->_globalMap[$key]] = $key;
125
+ }
126
+ }
127
+ $result = Varien_Object_Mapper::accumulateByMap(array($this, 'getDataUsingMethod'), $request, $map);
128
+ foreach ($privateRequestMap as $key) {
129
+ if (isset($this->_exportToRequestFilters[$key]) && isset($result[$key])) {
130
+ $callback = $this->_exportToRequestFilters[$key];
131
+ $privateKey = $result[$key];
132
+ $publicKey = $map[$this->_globalMap[$key]];
133
+ $result[$key] = call_user_func(array($this, $callback), $privateKey, $publicKey);
134
+ }
135
+ }
136
+
137
+ // TODO: Eventually fix this properly
138
+ // https://app.asana.com/0/56892580162484/63230238408321
139
+ $result['x_test'] = 'false';
140
+
141
+ return $result;
142
+ }
143
+
144
+ /**
145
+ * Import $this public data from a private response array
146
+ *
147
+ * @param array $privateResponseMap
148
+ * @param array $response
149
+ */
150
+ protected function _importFromResponse(array $privateResponseMap, array $response)
151
+ {
152
+ $map = array();
153
+ foreach ($privateResponseMap as $key) {
154
+ if (isset($this->_globalMap[$key])) {
155
+ $map[$key] = $this->_globalMap[$key];
156
+ }
157
+ if (isset($response[$key]) && isset($this->_importFromRequestFilters[$key])) {
158
+ $callback = $this->_importFromRequestFilters[$key];
159
+ $response[$key] = call_user_func(array($this, $callback), $response[$key], $key, $map[$key]);
160
+ }
161
+ }
162
+ Varien_Object_Mapper::accumulateByMap($response, array($this, 'setDataUsingMethod'), $map);
163
+ }
164
+
165
+ /**
166
+ * Prepare line items request
167
+ *
168
+ * Returns true if there were line items added
169
+ *
170
+ * @param array &$request
171
+ * @param int $i
172
+ * @return true|bool
173
+ */
174
+ protected function _exportLineItems(array &$request, $i = 0)
175
+ {
176
+ if (!$this->_cart) {
177
+ return;
178
+ }
179
+
180
+ // always add cart totals, even if line items are not requested
181
+ if ($this->_lineItemTotalExportMap) {
182
+ foreach ($this->_cart->getTotals() as $key => $total) {
183
+ if (isset($this->_lineItemTotalExportMap[$key])) { // !empty($total)
184
+ $privateKey = $this->_lineItemTotalExportMap[$key];
185
+ $request[$privateKey] = $this->_filterAmount($total);
186
+ }
187
+ }
188
+ }
189
+
190
+ // add cart line items
191
+ $items = $this->_cart->getItems();
192
+ if (empty($items) || !$this->getIsLineItemsEnabled()) {
193
+ return;
194
+ }
195
+ $result = null;
196
+ foreach ($items as $item) {
197
+ foreach ($this->_lineItemExportItemsFormat as $publicKey => $privateFormat) {
198
+ $result = true;
199
+ $value = $item->getDataUsingMethod($publicKey);
200
+ if (isset($this->_lineItemExportItemsFilters[$publicKey])) {
201
+ $callback = $this->_lineItemExportItemsFilters[$publicKey];
202
+ $value = call_user_func(array($this, $callback), $value);
203
+ }
204
+ if (is_float($value)) {
205
+ $value = $this->_filterAmount($value);
206
+ }
207
+ $request[sprintf($privateFormat, $i)] = $value;
208
+ }
209
+ $i++;
210
+ }
211
+ return $result;
212
+ }
213
+
214
+ /**
215
+ * Prepare shipping options request
216
+ * Returns false if there are no shipping options
217
+ *
218
+ * @param array &$request
219
+ * @param int $i
220
+ * @return bool
221
+ */
222
+ protected function _exportShippingOptions(array &$request, $i = 0)
223
+ {
224
+ $options = $this->getShippingOptions();
225
+ if (empty($options)) {
226
+ return false;
227
+ }
228
+ foreach ($options as $option) {
229
+ foreach ($this->_shippingOptionsExportItemsFormat as $publicKey => $privateFormat) {
230
+ $value = $option->getDataUsingMethod($publicKey);
231
+ if (is_float($value)) {
232
+ $value = $this->_filterAmount($value);
233
+ }
234
+ if (is_bool($value)) {
235
+ $value = $this->_filterBool($value);
236
+ }
237
+ $request[sprintf($privateFormat, $i)] = $value;
238
+ }
239
+ $i++;
240
+ }
241
+ return true;
242
+ }
243
+
244
+ /**
245
+ * Filter amounts in API calls
246
+ * @param float|string $value
247
+ * @return string
248
+ */
249
+ protected function _filterAmount($value)
250
+ {
251
+ return sprintf('%.2F', $value);
252
+ }
253
+
254
+ /**
255
+ * Filter boolean values in API calls
256
+ *
257
+ * @param mixed $value
258
+ * @return string
259
+ */
260
+ protected function _filterBool($value)
261
+ {
262
+ return ($value) ? 'true' : 'false';
263
+ }
264
+
265
+ /**
266
+ * Filter int values in API calls
267
+ *
268
+ * @param mixed $value
269
+ * @return int
270
+ */
271
+ protected function _filterInt($value)
272
+ {
273
+ return (int)$value;
274
+ }
275
+
276
+ /**
277
+ * Unified getter that looks in data or falls back to config
278
+ *
279
+ * @param string $key
280
+ * @param mixed $default
281
+ * @return mixed
282
+ */
283
+ protected function _getDataOrConfig($key, $default = null)
284
+ {
285
+ if ($this->hasData($key)) {
286
+ return $this->getData($key);
287
+ }
288
+ return $this->_config->$key ? $this->_config->$key : $default;
289
+ }
290
+
291
+
292
+ /**
293
+ * region_id workaround: Payment requires state code, try to find one in the address
294
+ * +/
295
+ * @param Varien_Object $address
296
+ * @return string
297
+ */
298
+ protected function _lookupRegionCodeFromAddress(Varien_Object $address)
299
+ {
300
+ if ($regionId = $address->getData('region_id')) {
301
+ $region = Mage::getModel('directory/region')->load($regionId);
302
+ if ($region->getId()) {
303
+ return $region->getCode();
304
+ }
305
+ }
306
+ return '';
307
+ }
308
+
309
+ /**
310
+ * Build query string from request
311
+ *
312
+ * @param array $request
313
+ * @return string
314
+ */
315
+ protected function _buildQuery($request)
316
+ {
317
+ return http_build_query($request);
318
+ }
319
+
320
+ /**
321
+ * Filter qty in API calls
322
+ * Paypal note: The value for quantity must be a positive integer. Null, zero, or negative numbers are not allowed.
323
+ *
324
+ * @param float|string|int $value
325
+ * @return string
326
+ */
327
+ protected function _filterQty($value)
328
+ {
329
+ return intval($value);
330
+ }
331
+
332
+ /**
333
+ * Street address workaround: divides address lines into parts by specified keys
334
+ * (keys should go as 3rd, 4th[...] parameters)
335
+ * +/
336
+ * @param Varien_Object $address
337
+ * @param array $to
338
+ */
339
+ protected function _importStreetFromAddress(Varien_Object $address, array &$to)
340
+ {
341
+ $keys = func_get_args(); array_shift($keys); array_shift($keys);
342
+ $street = $address->getStreet();
343
+ if (!$keys || !$street || !is_array($street)) {
344
+ return;
345
+ }
346
+
347
+ $street = Mage::helper('customer/address')
348
+ ->convertStreetLines($address->getStreet(), count($keys));
349
+
350
+ $i = 0;
351
+ foreach ($keys as $key) {
352
+ $to[$key] = isset($street[$i]) ? $street[$i]: '';
353
+ $i++;
354
+ }
355
+ }
356
+
357
+ }
app/code/local/Kash/Gateway/Model/Api/Bb.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * BB API wrappers model
5
+ */
6
+ class Kash_Gateway_Model_Api_Bb extends Kash_Gateway_Model_Api_Abstract
7
+ {
8
+ /**
9
+ * Global public interface map
10
+ * @var array
11
+ */
12
+ protected $_globalMap = array(
13
+ // each call
14
+ 'x_amount' => 'amount',
15
+ 'x_account_id' => 'x_account_id',
16
+ 'x_currency' => 'currency_code',
17
+ 'x_amount_tax' => 'tax_amount',
18
+ 'x_amount_shipping' => 'shipping_amount',
19
+ 'x_shop_country' => 'x_shop_country',
20
+ 'x_shop_name' => 'x_shop_name',
21
+ 'x_transaction_type' => 'x_transaction_type',
22
+ 'x_description' => 'x_description',
23
+ 'x_invoice' => 'x_invoice',
24
+ 'x_test' => 'x_test',
25
+ // backwards compatibility
26
+ 'x_customer_first_name' => 'firstname',
27
+ 'x_customer_last_name' => 'lastname',
28
+ 'x_customer_shipping_country' => 'countrycode',
29
+ 'x_url_callback' => 'x_url_callback',
30
+ 'x_url_cancel' => 'x_url_cancel',
31
+ 'x_url_complete' => 'x_url_complete',
32
+ 'x_reference' => 'x_reference'
33
+ );
34
+
35
+ /**
36
+ * Interface map for response
37
+ * @var array
38
+ */
39
+ public $responseMap = array(
40
+ 'Amount' => 'x_amount',
41
+ 'Result' => 'x_result',
42
+ 'Gateway Reference' => 'x_gateway_reference',
43
+ 'Test mode' => 'x_test'
44
+ );
45
+
46
+ /**
47
+ * Filter callbacks for preparing internal amounts to NVP request
48
+ *
49
+ * @var array
50
+ */
51
+ protected $_exportToRequestFilters = array(
52
+ 'x_amount' => '_filterAmount',
53
+ 'x_amount_shipping' => '_filterAmount',
54
+ 'x_amount_tax' => '_filterAmount',
55
+ 'x_test' => '_filterBool',
56
+ );
57
+
58
+ /**
59
+ * Line items export mapping settings
60
+ * @var array
61
+ */
62
+ protected $_lineItemTotalExportMap = array(
63
+ Kash_Gateway_Model_Cart::TOTAL_TAX => 'x_amount_tax',
64
+ Kash_Gateway_Model_Cart::TOTAL_SHIPPING => 'x_amount_shipping',
65
+ );
66
+
67
+ /**
68
+ * SetBBCheckout request/response map
69
+ * @var array
70
+ */
71
+ protected $_setBBCheckoutRequest = array(
72
+ 'x_reference', 'x_account_id', 'x_amount', 'x_currency', 'x_shop_country', 'x_shop_name', 'x_description', 'x_transaction_type',
73
+ 'x_invoice', 'x_test', 'x_amount_shipping', 'x_amount_tax', 'x_url_callback', 'x_url_cancel', 'x_url_complete'
74
+ );
75
+
76
+ /**
77
+ * SetBBCheckout response map
78
+ * @var array
79
+ */
80
+ protected $_setBBCheckoutResponse = array(
81
+ 'x_account_id', 'x_reference', 'x_currency', 'x_test', 'x_amount', 'x_gateway_reference', 'x_timestamp',
82
+ 'x_result', 'x_signature', 'x_amount_shipping', 'x_amount_tax'
83
+ );
84
+
85
+ /**
86
+ * Map for billing address import/export
87
+ * @var array
88
+ */
89
+ protected $_billingAddressMap = array(
90
+ 'x_customer_email' => 'email',
91
+ 'x_customer_first_name' => 'firstname',
92
+ 'x_customer_last_name' => 'lastname',
93
+ 'x_customer_shipping_country' => 'country_id', // iso-3166 two-character code
94
+ 'x_customer_shipping_state' => 'region',
95
+ 'x_customer_shipping_city' => 'city',
96
+ 'x_customer_shipping_address1' => 'street',
97
+ 'x_customer_shipping_address2' => 'street2',
98
+ 'x_customer_shipping_zip' => 'postcode',
99
+ 'x_customer_phone' => 'telephone',
100
+ );
101
+
102
+ /**
103
+ * Map for billing address to do request (not response)
104
+ * Merging with $_billingAddressMap
105
+ *
106
+ * @var array
107
+ */
108
+ protected $_billingAddressMapRequest = array();
109
+
110
+ /**
111
+ * Map for shipping address import/export (extends billing address mapper)
112
+ * @var array
113
+ */
114
+ protected $_shippingAddressMap = array(
115
+ 'x_customer_shipping_country' => 'country_id',
116
+ 'x_customer_shipping_state' => 'region',
117
+ 'x_customer_shipping_city' => 'city',
118
+ 'x_customer_shipping_address1' => 'street',
119
+ 'x_customer_shipping_address2' => 'street2',
120
+ 'x_customer_shipping_zip' => 'postcode',
121
+ 'x_customer_phone' => 'telephone',
122
+ );
123
+
124
+ /**
125
+ * Return request for API
126
+ *
127
+ */
128
+ public function callSetBBCheckout()
129
+ {
130
+ $request = $this->_exportToRequest($this->_setBBCheckoutRequest);
131
+ $this->_exportLineItems($request);
132
+
133
+ // import/suppress shipping address, if any
134
+ if ($this->getAddress()) {
135
+ $request = $this->_importAddresses($request);
136
+ }
137
+
138
+ $date = Zend_Date::now();
139
+ $request['x_timestamp'] = $date->getIso();
140
+ $request['x_signature'] = $this->getSignature($request, $this->getHmacKey());
141
+
142
+ return $request;
143
+ }
144
+
145
+ /**
146
+ * Gateway signing mechanism
147
+ *
148
+ * @param array $request
149
+ * @param $secret_key
150
+ * @return string
151
+ */
152
+ public function getSignature(array $request, $secret_key)
153
+ {
154
+ ksort($request);
155
+ $signature = '';
156
+ foreach ($request as $key => $val) {
157
+ if ($key === 'x_signature') {
158
+ continue;
159
+ }
160
+ $signature .= $key . $val;
161
+ }
162
+ $sig = hash_hmac('sha256', $signature, $secret_key, false);
163
+ return $sig;
164
+ }
165
+
166
+
167
+ /**
168
+ * @param array $request
169
+ * @return string
170
+ */
171
+ protected function _buildQuery($request)
172
+ {
173
+ return http_build_query($request);
174
+ }
175
+
176
+ /**
177
+ * Prepare request data basing on provided addresses
178
+ * +/
179
+ * @param array $to
180
+ * @return array
181
+ */
182
+ protected function _importAddresses(array $to)
183
+ {
184
+ $billingAddress = ($this->getBillingAddress()) ? $this->getBillingAddress() : $this->getAddress();
185
+ $shippingAddress = $this->getAddress();
186
+
187
+ $to = Varien_Object_Mapper::accumulateByMap(
188
+ $billingAddress,
189
+ $to,
190
+ array_merge(array_flip($this->_billingAddressMap), $this->_billingAddressMapRequest)
191
+ );
192
+ if ($regionCode = $this->_lookupRegionCodeFromAddress($billingAddress)) {
193
+ $to['x_customer_shipping_state'] = $regionCode;
194
+ }
195
+ if (!$this->getSuppressShipping()) {
196
+ $to = Varien_Object_Mapper::accumulateByMap($shippingAddress, $to, array_flip($this->_shippingAddressMap));
197
+ if ($regionCode = $this->_lookupRegionCodeFromAddress($shippingAddress)) {
198
+ $to['x_customer_shipping_state'] = $regionCode;
199
+ }
200
+ $this->_importStreetFromAddress($billingAddress, $to, 'x_customer_shipping_address1', 'x_customer_shipping_address2');
201
+ $this->_importStreetFromAddress($shippingAddress, $to, 'x_customer_shipping_address1', 'x_customer_shipping_address2');
202
+ }
203
+ return $to;
204
+ }
205
+
206
+ protected function getXAccountId()
207
+ {
208
+ $value = $this->_getDataOrConfig('x_account_id');
209
+ return $value;
210
+ }
211
+
212
+ protected function getXShopCountry()
213
+ {
214
+ $value = $this->_config->getMerchantCountry();
215
+ return $value;
216
+ }
217
+
218
+ protected function getXShopName()
219
+ {
220
+ $value = $this->_getDataOrConfig('x_shop_name');
221
+ return $value;
222
+ }
223
+
224
+ protected function getXTest()
225
+ {
226
+ $value = $this->_getDataOrConfig('x_test');
227
+ return $value;
228
+ }
229
+
230
+ public function getHmacKey()
231
+ {
232
+ $value = $this->_getDataOrConfig('server_key');
233
+ return $value;
234
+ }
235
+ }
app/code/local/Kash/Gateway/Model/Cart.php ADDED
@@ -0,0 +1,497 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Payment-specific model for shopping cart items and totals
4
+ */
5
+ class Kash_Gateway_Model_Cart
6
+ {
7
+ /**
8
+ * Totals that Payment suppports when passing shopping cart
9
+ *
10
+ * @var string
11
+ */
12
+ const TOTAL_SUBTOTAL = 'subtotal';
13
+ const TOTAL_DISCOUNT = 'discount';
14
+ const TOTAL_TAX = 'tax';
15
+ const TOTAL_SHIPPING = 'shipping';
16
+
17
+ /**
18
+ * Order or quote instance
19
+ *
20
+ * @var Mage_Sales_Model_Order
21
+ * @var Mage_Sales_Model_Quote
22
+ */
23
+ protected $_salesEntity = null;
24
+
25
+ /**
26
+ * Rendered cart items
27
+ * Array of Varien_Objects
28
+ *
29
+ * @var array
30
+ */
31
+ protected $_items = array();
32
+
33
+ /**
34
+ * Rendered cart totals
35
+ * Associative array with the keys from constants above
36
+ *
37
+ * @var array
38
+ */
39
+ protected $_totals = array();
40
+
41
+ /**
42
+ * Set of optional descriptions for the item that may replace a total and composed of several amounts
43
+ * Array of strings
44
+ *
45
+ * @var array
46
+ */
47
+ protected $_totalLineItemDescriptions = array();
48
+
49
+ /**
50
+ * Lazy initialization indicator for rendering
51
+ *
52
+ * @var bool
53
+ */
54
+ protected $_shouldRender = true;
55
+
56
+ /**
57
+ * Validation result for the rendered cart items
58
+ *
59
+ * @var bool
60
+ */
61
+ protected $_areItemsValid = false;
62
+
63
+ /**
64
+ * Validation result for the rendered totals
65
+ *
66
+ * @var bool
67
+ */
68
+ protected $_areTotalsValid = false;
69
+
70
+ /**
71
+ * Whether to render discount total as a line item
72
+ * Use case: WPP
73
+ *
74
+ * @var bool
75
+ */
76
+ protected $_isDiscountAsItem = false;
77
+
78
+ /**
79
+ * Whether to render shipping total as a line item
80
+ * Use case: WPS
81
+ *
82
+ * @var bool
83
+ */
84
+ protected $_isShippingAsItem = false;
85
+
86
+ /**
87
+ * Require instance of an order or a quote
88
+ *
89
+ * @param array $params
90
+ */
91
+ public function __construct($params = array())
92
+ {
93
+ $salesEntity = array_shift($params);
94
+ if (is_object($salesEntity)
95
+ && (($salesEntity instanceof Mage_Sales_Model_Order) || ($salesEntity instanceof Mage_Sales_Model_Quote))) {
96
+ $this->_salesEntity = $salesEntity;
97
+ } else {
98
+ throw new Exception('Invalid sales entity provided.');
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Getter for the current sales entity
104
+ *
105
+ * @return Mage_Sales_Model_Order
106
+ * @return Mage_Sales_Model_Quote
107
+ */
108
+ public function getSalesEntity()
109
+ {
110
+ return $this->_salesEntity;
111
+ }
112
+
113
+ /**
114
+ * Render and get line items
115
+ * By default returns false if the items are invalid
116
+ *
117
+ * @param bool $bypassValidation
118
+ * @return array|false
119
+ */
120
+ public function getItems($bypassValidation = false)
121
+ {
122
+ $this->_render();
123
+ if (!$bypassValidation && !$this->_areItemsValid) {
124
+ return false;
125
+ }
126
+ return $this->_items;
127
+ }
128
+
129
+ /**
130
+ * Render and get totals
131
+ * If the totals are invalid for any reason, they will be merged into one amount (subtotal is utilized for it)
132
+ * An option to substract discount from the subtotal is available
133
+ *
134
+ * @param bool $mergeDiscount
135
+ * @return array
136
+ */
137
+ public function getTotals($mergeDiscount = false)
138
+ {
139
+ $this->_render();
140
+
141
+ // cut down totals to one total if they are invalid
142
+ if (!$this->_areTotalsValid) {
143
+ $totals = array(
144
+ self::TOTAL_SUBTOTAL => $this->_totals[self::TOTAL_SUBTOTAL] + $this->_totals[self::TOTAL_TAX]
145
+ );
146
+ if (!$this->_isShippingAsItem) {
147
+ $totals[self::TOTAL_SUBTOTAL] += $this->_totals[self::TOTAL_SHIPPING];
148
+ }
149
+ if (!$this->_isDiscountAsItem) {
150
+ $totals[self::TOTAL_SUBTOTAL] -= $this->_totals[self::TOTAL_DISCOUNT];
151
+ }
152
+ return $totals;
153
+ } elseif ($mergeDiscount) {
154
+ $totals = $this->_totals;
155
+ unset($totals[self::TOTAL_DISCOUNT]);
156
+ if (!$this->_isDiscountAsItem) {
157
+ $totals[self::TOTAL_SUBTOTAL] -= $this->_totals[self::TOTAL_DISCOUNT];
158
+ }
159
+ return $totals;
160
+ }
161
+ return $this->_totals;
162
+ }
163
+
164
+ /**
165
+ * Add a line item
166
+ *
167
+ * @param string $name
168
+ * @param numeric $qty
169
+ * @param float $amount
170
+ * @param string $identifier
171
+ * @return Varien_Object
172
+ */
173
+ public function addItem($name, $qty, $amount, $identifier = null)
174
+ {
175
+ $this->_shouldRender = true;
176
+ $item = new Varien_Object(array(
177
+ 'name' => $name,
178
+ 'qty' => $qty,
179
+ 'amount' => (float)$amount,
180
+ ));
181
+ if ($identifier) {
182
+ $item->setData('id', $identifier);
183
+ }
184
+ $this->_items[] = $item;
185
+ return $item;
186
+ }
187
+
188
+ /**
189
+ * Remove item from cart by identifier
190
+ *
191
+ * @param string $identifier
192
+ * @return bool
193
+ */
194
+ public function removeItem($identifier)
195
+ {
196
+ foreach ($this->_items as $key => $item) {
197
+ if ($item->getId() == $identifier) {
198
+ unset($this->_items[$key]);
199
+ return true;
200
+ }
201
+ }
202
+ return false;
203
+ }
204
+
205
+ /**
206
+ * Compound the specified amount with the specified total
207
+ *
208
+ * @param string $code
209
+ * @param float $amount
210
+ * @param string $lineItemDescription
211
+ * @return Kash_Gateway_Model_Cart
212
+ */
213
+ public function updateTotal($code, $amount, $lineItemDescription = null)
214
+ {
215
+ $this->_shouldRender = true;
216
+ if (isset($this->_totals[$code])) {
217
+ $this->_totals[$code] += $amount;
218
+ if ($lineItemDescription) {
219
+ $this->_totalLineItemDescriptions[$code][] = $lineItemDescription;
220
+ }
221
+ }
222
+ return $this;
223
+ }
224
+
225
+ /**
226
+ * Get/Set whether to render the discount total as a line item
227
+ *
228
+ * @param $setValue
229
+ * @return bool|Kash_Gateway_Model_Cart
230
+ */
231
+ public function isDiscountAsItem($setValue = null)
232
+ {
233
+ return $this->_totalAsItem('_isDiscountAsItem', $setValue);
234
+ }
235
+
236
+ /**
237
+ * Get/Set whether to render the discount total as a line item
238
+ *
239
+ * @param $setValue
240
+ * @return bool|Kash_Gateway_Model_Cart
241
+ */
242
+ public function isShippingAsItem($setValue = null)
243
+ {
244
+ return $this->_totalAsItem('_isShippingAsItem', $setValue);
245
+ }
246
+
247
+ /**
248
+ * (re)Render all items and totals
249
+ */
250
+ protected function _render()
251
+ {
252
+ if (!$this->_shouldRender) {
253
+ return;
254
+ }
255
+
256
+ // regular items from the sales entity
257
+ $this->_items = array();
258
+ foreach ($this->_salesEntity->getAllItems() as $item) {
259
+ if (!$item->getParentItem()) {
260
+ $this->_addRegularItem($item);
261
+ }
262
+ }
263
+ end($this->_items);
264
+ $lastRegularItemKey = key($this->_items);
265
+
266
+ // regular totals
267
+ $shippingDescription = '';
268
+ if ($this->_salesEntity instanceof Mage_Sales_Model_Order) {
269
+ $shippingDescription = $this->_salesEntity->getShippingDescription();
270
+ $this->_totals = array(
271
+ self::TOTAL_SUBTOTAL => $this->_salesEntity->getBaseSubtotal(),
272
+ self::TOTAL_TAX => $this->_salesEntity->getBaseTaxAmount(),
273
+ self::TOTAL_SHIPPING => $this->_salesEntity->getBaseShippingAmount(),
274
+ self::TOTAL_DISCOUNT => abs($this->_salesEntity->getBaseDiscountAmount()),
275
+ );
276
+ $this->_applyHiddenTaxWorkaround($this->_salesEntity);
277
+ } else {
278
+ $address = $this->_salesEntity->getIsVirtual() ?
279
+ $this->_salesEntity->getBillingAddress() : $this->_salesEntity->getShippingAddress();
280
+ $shippingDescription = $address->getShippingDescription();
281
+ $this->_totals = array (
282
+ self::TOTAL_SUBTOTAL => $this->_salesEntity->getBaseSubtotal(),
283
+ self::TOTAL_TAX => $address->getBaseTaxAmount(),
284
+ self::TOTAL_SHIPPING => $address->getBaseShippingAmount(),
285
+ self::TOTAL_DISCOUNT => abs($address->getBaseDiscountAmount()),
286
+ );
287
+ $this->_applyHiddenTaxWorkaround($address);
288
+ }
289
+ $originalDiscount = $this->_totals[self::TOTAL_DISCOUNT];
290
+
291
+ // arbitrary items, total modifications
292
+ Mage::dispatchEvent('payment_prepare_line_items', array('payment_cart' => $this));
293
+
294
+ // distinguish original discount among the others
295
+ if ($originalDiscount > 0.0001 && isset($this->_totalLineItemDescriptions[self::TOTAL_DISCOUNT])) {
296
+ $this->_totalLineItemDescriptions[self::TOTAL_DISCOUNT][] = Mage::helper('sales')->__('Discount (%s)', Mage::app()->getStore()->convertPrice($originalDiscount, true, false));
297
+ }
298
+
299
+ // discount, shipping as items
300
+ if ($this->_isDiscountAsItem && $this->_totals[self::TOTAL_DISCOUNT]) {
301
+ $this->addItem(Mage::helper('kash_gateway')->__('Discount'), 1, -1.00 * $this->_totals[self::TOTAL_DISCOUNT],
302
+ $this->_renderTotalLineItemDescriptions(self::TOTAL_DISCOUNT)
303
+ );
304
+ }
305
+ $shippingItemId = $this->_renderTotalLineItemDescriptions(self::TOTAL_SHIPPING, $shippingDescription);
306
+ if ($this->_isShippingAsItem && (float)$this->_totals[self::TOTAL_SHIPPING]) {
307
+ $this->addItem(Mage::helper('kash_gateway')->__('Shipping'), 1, (float)$this->_totals[self::TOTAL_SHIPPING],
308
+ $shippingItemId
309
+ );
310
+ }
311
+
312
+ // compound non-regular items into subtotal
313
+ foreach ($this->_items as $key => $item) {
314
+ if ($key > $lastRegularItemKey && $item->getAmount() != 0) {
315
+ $this->_totals[self::TOTAL_SUBTOTAL] += $item->getAmount();
316
+ }
317
+ }
318
+
319
+ $this->_validate();
320
+ // if cart items are invalid, prepare cart for transfer without line items
321
+ if (!$this->_areItemsValid) {
322
+ $this->removeItem($shippingItemId);
323
+ }
324
+
325
+ $this->_shouldRender = false;
326
+ }
327
+
328
+ /**
329
+ * Merge multiple descriptions by a total code into a string
330
+ *
331
+ * @param string $code
332
+ * @param string $prepend
333
+ * @param string $append
334
+ * @param string $glue
335
+ * @return string
336
+ */
337
+ protected function _renderTotalLineItemDescriptions($code, $prepend = '', $append = '', $glue = '; ')
338
+ {
339
+ $result = array();
340
+ if ($prepend) {
341
+ $result[] = $prepend;
342
+ }
343
+ if (isset($this->_totalLineItemDescriptions[$code])) {
344
+ $result = array_merge($this->_totalLineItemDescriptions[$code]);
345
+ }
346
+ if ($append) {
347
+ $result[] = $append;
348
+ }
349
+ return implode($glue, $result);
350
+ }
351
+
352
+ /**
353
+ * Check the line items and totals according to Payment business logic limitations
354
+ */
355
+ protected function _validate()
356
+ {
357
+ $this->_areItemsValid = true;
358
+ $this->_areTotalsValid = false;
359
+
360
+ $referenceAmount = $this->_salesEntity->getBaseGrandTotal();
361
+
362
+ $itemsSubtotal = 0;
363
+ foreach ($this->_items as $i) {
364
+ $itemsSubtotal = $itemsSubtotal + $i['qty'] * $i['amount'];
365
+ }
366
+ $sum = $itemsSubtotal + $this->_totals[self::TOTAL_TAX];
367
+ if (!$this->_isShippingAsItem) {
368
+ $sum += $this->_totals[self::TOTAL_SHIPPING];
369
+ }
370
+ if (!$this->_isDiscountAsItem) {
371
+ $sum -= $this->_totals[self::TOTAL_DISCOUNT];
372
+ }
373
+ /**
374
+ * numbers are intentionally converted to strings because of possible comparison error
375
+ * see http://php.net/float
376
+ */
377
+ // match sum of all the items and totals to the reference amount
378
+ if (sprintf('%.4F', $sum) != sprintf('%.4F', $referenceAmount)) {
379
+ $adjustment = $sum - $referenceAmount;
380
+ $this->_totals[self::TOTAL_SUBTOTAL] = $this->_totals[self::TOTAL_SUBTOTAL] - $adjustment;
381
+ }
382
+
383
+ // Payment requires to have discount less than items subtotal
384
+ if (!$this->_isDiscountAsItem) {
385
+ $this->_areTotalsValid = round($this->_totals[self::TOTAL_DISCOUNT], 4) < round($itemsSubtotal, 4);
386
+ } else {
387
+ $this->_areTotalsValid = $itemsSubtotal > 0.00001;
388
+ }
389
+
390
+ $this->_areItemsValid = $this->_areItemsValid && $this->_areTotalsValid;
391
+ }
392
+
393
+ /**
394
+ * Check whether items are valid
395
+ *
396
+ * @return bool
397
+ */
398
+ public function areItemsValid()
399
+ {
400
+ return $this->_areItemsValid;
401
+ }
402
+
403
+ /**
404
+ * Add a usual line item with amount and qty
405
+ *
406
+ * @param Varien_Object $salesItem
407
+ * @return Varien_Object
408
+ */
409
+ protected function _addRegularItem(Varien_Object $salesItem)
410
+ {
411
+ if ($this->_salesEntity instanceof Mage_Sales_Model_Order) {
412
+ $qty = (int) $salesItem->getQtyOrdered();
413
+ $amount = (float) $salesItem->getBasePrice();
414
+ // TODO: nominal item for order
415
+ } else {
416
+ $qty = (int) $salesItem->getTotalQty();
417
+ $amount = $salesItem->isNominal() ? 0 : (float) $salesItem->getBaseCalculationPrice();
418
+ }
419
+ // workaround in case if item subtotal precision is not compatible with Payment (.2)
420
+ $subAggregatedLabel = '';
421
+ if ($amount - round($amount, 2)) {
422
+ $amount = $amount * $qty;
423
+ $subAggregatedLabel = ' x' . $qty;
424
+ $qty = 1;
425
+ }
426
+
427
+ // aggregate item price if item qty * price does not match row total
428
+ if (($amount * $qty) != $salesItem->getBaseRowTotal()) {
429
+ $amount = (float) $salesItem->getBaseRowTotal();
430
+ $subAggregatedLabel = ' x' . $qty;
431
+ $qty = 1;
432
+ }
433
+
434
+ return $this->addItem($salesItem->getName() . $subAggregatedLabel, $qty, $amount, $salesItem->getSku());
435
+ }
436
+
437
+ /**
438
+ * Get/Set for the specified variable.
439
+ * If the value changes, the re-rendering is commenced
440
+ *
441
+ * @param string $var
442
+ * @param $setValue
443
+ * @return bool|Kash_Gateway_Model_Cart
444
+ */
445
+ private function _totalAsItem($var, $setValue = null)
446
+ {
447
+ if (null !== $setValue) {
448
+ if ($setValue != $this->$var) {
449
+ $this->_shouldRender = true;
450
+ }
451
+ $this->$var = $setValue;
452
+ return $this;
453
+ }
454
+ return $this->$var;
455
+ }
456
+
457
+ /**
458
+ * Add "hidden" discount and shipping tax
459
+ *
460
+ * Go ahead, try to understand ]:->
461
+ *
462
+ * Tax settings for getting "discount tax":
463
+ * - Catalog Prices = Including Tax
464
+ * - Apply Customer Tax = After Discount
465
+ * - Apply Discount on Prices = Including Tax
466
+ *
467
+ * Test case for getting "hidden shipping tax":
468
+ * - Make sure shipping is taxable (set shipping tax class)
469
+ * - Catalog Prices = Including Tax
470
+ * - Shipping Prices = Including Tax
471
+ * - Apply Customer Tax = After Discount
472
+ * - Create a shopping cart price rule with % discount applied to the Shipping Amount
473
+ * - run shopping cart and estimate shipping
474
+ *
475
+ * @param Mage_Core_Model_Abstract $salesEntity
476
+ */
477
+ private function _applyHiddenTaxWorkaround($salesEntity)
478
+ {
479
+ $this->_totals[self::TOTAL_TAX] += (float)$salesEntity->getBaseHiddenTaxAmount();
480
+ $this->_totals[self::TOTAL_TAX] += (float)$salesEntity->getBaseShippingHiddenTaxAmount();
481
+ }
482
+
483
+ /**
484
+ * Check whether any item has negative amount
485
+ *
486
+ * @return bool
487
+ */
488
+ public function hasNegativeItemAmount()
489
+ {
490
+ foreach ($this->_items as $item) {
491
+ if ($item->getAmount() < 0) {
492
+ return true;
493
+ }
494
+ }
495
+ return false;
496
+ }
497
+ }
app/code/local/Kash/Gateway/Model/Checkout.php ADDED
@@ -0,0 +1,655 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Wrapper that performs Payment BB and Checkout communication
5
+ * Use current Payment BB method instance
6
+ *
7
+ * @author Blue Badger <jonathan@badger.blue>
8
+ */
9
+ class Kash_Gateway_Model_Checkout
10
+ {
11
+ /**
12
+ * @var Mage_Sales_Model_Quote
13
+ */
14
+ public $_quote = null;
15
+
16
+ /**
17
+ * Config instance
18
+ * @var Kash_Gateway_Model_Config
19
+ */
20
+ protected $_config = null;
21
+
22
+ /**
23
+ * API instance
24
+ * @var Kash_Gateway_Model_Api_Bb
25
+ */
26
+ protected $_api = null;
27
+
28
+ /**
29
+ * Api Model Type
30
+ *
31
+ * @var string
32
+ */
33
+ protected $_apiType = 'kash_gateway/api_bb';
34
+
35
+ /**
36
+ * Payment method type
37
+ */
38
+ protected $_methodType = Kash_Gateway_Model_Config::METHOD_GATEWAY_KASH;
39
+
40
+ /**
41
+ * Params response
42
+ */
43
+ protected $_params = null;
44
+
45
+ /**
46
+ * State helper variables
47
+ * @var string
48
+ */
49
+ protected $_redirectUrl = '';
50
+ protected $_pendingPaymentMessage = '';
51
+ protected $_checkoutRedirectUrl = '';
52
+
53
+ /**
54
+ * @var Mage_Customer_Model_Session
55
+ */
56
+ protected $_customerSession;
57
+
58
+ /**
59
+ * Redirect urls supposed to be set to support giropay
60
+ *
61
+ * @var array
62
+ */
63
+ protected $_giropayUrls = array();
64
+
65
+ /**
66
+ * Customer ID
67
+ *
68
+ * @var int
69
+ */
70
+ protected $_customerId = null;
71
+
72
+ /**
73
+ * Order
74
+ *
75
+ * @var Mage_Sales_Model_Quote
76
+ */
77
+ protected $_order = null;
78
+
79
+ /**
80
+ * Set quote and config instances
81
+ * @param array $params
82
+ * @throws Exception
83
+ */
84
+ public function __construct($params = array())
85
+ {
86
+ if (isset($params['quote']) && $params['quote'] instanceof Mage_Sales_Model_Quote) {
87
+ $this->_quote = $params['quote'];
88
+ } else {
89
+ throw new Exception('Quote instance is required.');
90
+ }
91
+ if (isset($params['config']) && $params['config'] instanceof Kash_Gateway_Model_Config) {
92
+ $this->_config = $params['config'];
93
+ } else {
94
+ throw new Exception('Config instance is required.');
95
+ }
96
+ $this->_customerSession = isset($params['session']) && $params['session'] instanceof Mage_Customer_Model_Session
97
+ ? $params['session'] : Mage::getSingleton('customer/session');
98
+ }
99
+
100
+ /**
101
+ * Setter that enables giropay redirects flow
102
+ * +/
103
+ * @param string $callbackUrl - payment callback
104
+ * @param string $cancelUrl - payment cancellation result
105
+ * @param string $completeUrl - complete payment result
106
+ * @return $this
107
+ */
108
+ public function prepareGiropayUrls($callbackUrl, $cancelUrl, $completeUrl)
109
+ {
110
+ $this->_giropayUrls = array($callbackUrl, $cancelUrl, $completeUrl);
111
+ return $this;
112
+ }
113
+
114
+ /**
115
+ * Setter for customer Id
116
+ *
117
+ * @param int $id
118
+ * @return $this
119
+ */
120
+ public function setCustomerId($id)
121
+ {
122
+ $this->_customerId = $id;
123
+ return $this;
124
+ }
125
+
126
+ /**
127
+ * Setter for customer
128
+ *
129
+ * @param Mage_Customer_Model_Customer $customer
130
+ * @return $this
131
+ */
132
+ public function setCustomer($customer)
133
+ {
134
+ $this->_quote->assignCustomer($customer);
135
+ $this->_customerId = $customer->getId();
136
+ return $this;
137
+ }
138
+
139
+ /**
140
+ * Setter for customer with billing and shipping address changing ability
141
+ *
142
+ * @param Mage_Customer_Model_Customer $customer
143
+ * @param Mage_Sales_Model_Quote_Address $billingAddress
144
+ * @param Mage_Sales_Model_Quote_Address $shippingAddress
145
+ * @return $this
146
+ */
147
+ public function setCustomerWithAddressChange($customer, $billingAddress = null, $shippingAddress = null)
148
+ {
149
+ $this->_quote->assignCustomerWithAddressChange($customer, $billingAddress, $shippingAddress);
150
+ $this->_customerId = $customer->getId();
151
+ return $this;
152
+ }
153
+
154
+ /**
155
+ * Reserve order ID for specified quote and start checkout on Payment
156
+ *
157
+ * @return mixed
158
+ */
159
+ public function start()
160
+ {
161
+ //$this->_quote->setCouponCode('code_test');
162
+ $this->_quote->collectTotals();
163
+
164
+ if (!$this->_quote->getGrandTotal() && !$this->_quote->hasNominalItems()) {
165
+ Mage::throwException(Mage::helper('kash_gateway')->__('Payment does not support processing orders with zero amount. To complete your purchase, proceed to the standard checkout process.'));
166
+ }
167
+
168
+ //Mage::helper('kash_gateway/checkout')->restoreQuote();
169
+ $this->_quote->reserveOrderId()->save();
170
+ // prepare API
171
+ $this->_getApi();
172
+ $this->_api->setAmount($this->_quote->getGrandTotal())
173
+ ->setCurrencyCode($this->_quote->getBaseCurrencyCode())
174
+ ->setXInvoice($this->_quote->getReservedOrderId());
175
+ list($callbackUrl, $cancelUrl, $completeUrl) = $this->_giropayUrls;
176
+ $this->_api->addData(array(
177
+ 'x_url_callback' => $callbackUrl,
178
+ 'x_url_cancel' => $cancelUrl,
179
+ 'x_url_complete' => $completeUrl,
180
+ 'x_transaction_type' => 'sale',
181
+ 'x_description' => 'Order #' . $this->_quote->getReservedOrderId(),
182
+ 'x_reference' => $this->_quote->getReservedOrderId(),
183
+ ));
184
+
185
+ // supress or export shipping address
186
+ if ($this->_quote->getIsVirtual()) {
187
+ $this->_api->setRequireBillingAddress(1);
188
+
189
+ $this->_api->setSuppressShipping(true);
190
+ } else {
191
+ $address = $this->_quote->getShippingAddress();
192
+ if (true === $address->validate()) {
193
+ $this->_api->setAddress($address);
194
+ }
195
+ $this->_quote->getPayment()->save();
196
+ }
197
+
198
+ // add line items
199
+ $paymentCart = Mage::getModel('kash_gateway/cart', array($this->_quote));
200
+ $this->_api->setPaymentCart($paymentCart);
201
+
202
+ // call API and redirect with token
203
+ $token = $this->_api->getToken();
204
+ $token = $this->_api->callSetBBCheckout();
205
+ $this->_redirectUrl = $this->_config->post_url;
206
+
207
+ $this->_quote->getPayment()->save();
208
+ return $token;
209
+ }
210
+
211
+ /**
212
+ * Check whether system can skip order review page before placing order
213
+ * +/
214
+ * @return bool
215
+ */
216
+ public function canSkipOrderReviewStep()
217
+ {
218
+ return $this->_config->isOrderReviewStepDisabled();
219
+ }
220
+
221
+ /**
222
+ * Set shipping method to quote, if needed
223
+ * @param string $methodCode
224
+ */
225
+ public function updateShippingMethod($methodCode)
226
+ {
227
+ if (!$this->_quote->getIsVirtual() && $shippingAddress = $this->_quote->getShippingAddress()) {
228
+ if ($methodCode != $shippingAddress->getShippingMethod()) {
229
+ $this->_ignoreAddressValidation();
230
+ $shippingAddress->setShippingMethod($methodCode)->setCollectShippingRates(true);
231
+ $this->_quote->collectTotals()->save();
232
+ }
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Place the order and recurring payment profiles when customer returned from payment
238
+ * Until this moment all quote data must be valid
239
+ */
240
+ public function place()
241
+ {
242
+ $isNewCustomer = false;
243
+ switch ($this->getCheckoutMethod()) {
244
+ case Mage_Checkout_Model_Type_Onepage::METHOD_GUEST:
245
+ $this->_prepareGuestQuote();
246
+ break;
247
+ case Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER:
248
+ $this->_prepareNewCustomerQuote();
249
+ $isNewCustomer = true;
250
+ break;
251
+ default:
252
+ $this->_prepareCustomerQuote();
253
+ break;
254
+ }
255
+
256
+ $this->setAdditionalInformation();
257
+ $this->_ignoreAddressValidation();
258
+ $this->_applyDiscount();
259
+ $this->_quote->collectTotals();
260
+ $service = Mage::getModel('sales/service_quote', $this->_quote);
261
+ $service->submitAll();
262
+ $this->_quote->save();
263
+
264
+ if ($isNewCustomer) {
265
+ try {
266
+ $this->_involveNewCustomer();
267
+ } catch (Exception $e) {
268
+ Mage::logException($e);
269
+ }
270
+ }
271
+
272
+ /** @var $order Mage_Sales_Model_Order */
273
+ $order = $service->getOrder();
274
+ if (!$order) {
275
+ return;
276
+ }
277
+
278
+ switch ($order->getState()) {
279
+ // even after placement payment can disallow to authorize/capture, but will wait until bank transfers money
280
+ case Mage_Sales_Model_Order::STATE_PENDING_PAYMENT:
281
+ // TODO
282
+ break;
283
+ // regular placement, when everything is ok
284
+ case Mage_Sales_Model_Order::STATE_PROCESSING:
285
+ case Mage_Sales_Model_Order::STATE_COMPLETE:
286
+ case Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW:
287
+ $order->queueNewOrderEmail();
288
+ break;
289
+ }
290
+ $this->_order = $order;
291
+ }
292
+
293
+ /**
294
+ * Set additional information
295
+ */
296
+ public function setAdditionalInformation()
297
+ {
298
+ $payment = $this->_quote->getPayment();
299
+ $payment->setXGatewayReference($this->getParams('x_gateway_reference'));
300
+
301
+ $params = $this->getParams();
302
+ $result = array();
303
+ foreach ($this->_api->responseMap as $key => $val) {
304
+ $result[$key] = $params[$val];
305
+ }
306
+ $payment->setAdditionalInformation($result);
307
+ }
308
+
309
+ /** +/
310
+ * Make sure addresses will be saved without validation errors
311
+ */
312
+ public function _ignoreAddressValidation()
313
+ {
314
+ $this->_quote->getBillingAddress()->setShouldIgnoreValidation(true);
315
+ if (!$this->_quote->getIsVirtual()) {
316
+ $this->_quote->getShippingAddress()->setShouldIgnoreValidation(true);
317
+ if (!$this->_quote->getBillingAddress()->getEmail()) {
318
+ $this->_quote->getBillingAddress()->setSameAsBilling(1);
319
+ }
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Determine whether redirect somewhere specifically is required
325
+ *
326
+ * @return string
327
+ */
328
+ public function getRedirectUrl()
329
+ {
330
+ return $this->_redirectUrl;
331
+ }
332
+
333
+ /**
334
+ * Return order
335
+ * +/
336
+ * @return Mage_Sales_Model_Order
337
+ */
338
+ public function getOrder()
339
+ {
340
+ return $this->_order;
341
+ }
342
+
343
+ /**
344
+ * Get checkout method
345
+ * +/
346
+ * @return string
347
+ */
348
+ public function getCheckoutMethod()
349
+ {
350
+ if ($this->getCustomerSession()->isLoggedIn()) {
351
+ return Mage_Checkout_Model_Type_Onepage::METHOD_CUSTOMER;
352
+ }
353
+ if (!$this->_quote->getCheckoutMethod()) {
354
+ if (Mage::helper('checkout')->isAllowedGuestCheckout($this->_quote)) {
355
+ $this->_quote->setCheckoutMethod(Mage_Checkout_Model_Type_Onepage::METHOD_GUEST);
356
+ } else {
357
+ $this->_quote->setCheckoutMethod(Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER);
358
+ }
359
+ }
360
+ return $this->_quote->getCheckoutMethod();
361
+ }
362
+
363
+ /** +/
364
+ * @return Kash_Gateway_Model_Api_Bb
365
+ */
366
+ public function _getApi()
367
+ {
368
+ if (null === $this->_api) {
369
+ $this->_api = Mage::getModel($this->_apiType)->setConfigObject($this->_config);
370
+ }
371
+ return $this->_api;
372
+ }
373
+
374
+ /**
375
+ * Prepare quote for guest checkout order submit
376
+ *
377
+ * @return $this
378
+ */
379
+ protected function _prepareGuestQuote()
380
+ {
381
+ $quote = $this->_quote;
382
+ $quote->setCustomerId(null)
383
+ ->setCustomerEmail($quote->getBillingAddress()->getEmail())
384
+ ->setCustomerIsGuest(true)
385
+ ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID);
386
+ return $this;
387
+ }
388
+
389
+ /**
390
+ * Checks if customer with email coming from Express checkout exists
391
+ * +/
392
+ * @return int
393
+ */
394
+ protected function _lookupCustomerId()
395
+ {
396
+ return Mage::getModel('customer/customer')
397
+ ->setWebsiteId(Mage::app()->getWebsite()->getId())
398
+ ->loadByEmail($this->_quote->getCustomerEmail())
399
+ ->getId();
400
+ }
401
+
402
+ /**
403
+ * Prepare quote for customer registration and customer order submit
404
+ * and restore magento customer data from quote
405
+ *
406
+ * @return $this
407
+ */
408
+ protected function _prepareNewCustomerQuote()
409
+ {
410
+ $quote = $this->_quote;
411
+ $billing = $quote->getBillingAddress();
412
+ $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress();
413
+
414
+ $customerId = $this->_lookupCustomerId();
415
+ if ($customerId) {
416
+ $this->getCustomerSession()->loginById($customerId);
417
+ return $this->_prepareCustomerQuote();
418
+ }
419
+
420
+ $customer = $quote->getCustomer();
421
+ /** @var $customer Mage_Customer_Model_Customer */
422
+ $customerBilling = $billing->exportCustomerAddress();
423
+ $customer->addAddress($customerBilling);
424
+ $billing->setCustomerAddress($customerBilling);
425
+ $customerBilling->setIsDefaultBilling(true);
426
+ if ($shipping && !$shipping->getSameAsBilling()) {
427
+ $customerShipping = $shipping->exportCustomerAddress();
428
+ $customer->addAddress($customerShipping);
429
+ $shipping->setCustomerAddress($customerShipping);
430
+ $customerShipping->setIsDefaultShipping(true);
431
+ } elseif ($shipping) {
432
+ $customerBilling->setIsDefaultShipping(true);
433
+ }
434
+
435
+ if ($quote->getCustomerDob() && !$billing->getCustomerDob()) {
436
+ $billing->setCustomerDob($quote->getCustomerDob());
437
+ }
438
+
439
+ if ($quote->getCustomerTaxvat() && !$billing->getCustomerTaxvat()) {
440
+ $billing->setCustomerTaxvat($quote->getCustomerTaxvat());
441
+ }
442
+
443
+ if ($quote->getCustomerGender() && !$billing->getCustomerGender()) {
444
+ $billing->setCustomerGender($quote->getCustomerGender());
445
+ }
446
+
447
+ Mage::helper('core')->copyFieldset('checkout_onepage_billing', 'to_customer', $billing, $customer);
448
+ $customer->setEmail($quote->getCustomerEmail());
449
+ $customer->setPrefix($quote->getCustomerPrefix());
450
+ $customer->setFirstname($quote->getCustomerFirstname());
451
+ $customer->setMiddlename($quote->getCustomerMiddlename());
452
+ $customer->setLastname($quote->getCustomerLastname());
453
+ $customer->setSuffix($quote->getCustomerSuffix());
454
+ $customer->setPassword($customer->decryptPassword($quote->getPasswordHash()));
455
+ $customer->setPasswordHash($customer->hashPassword($customer->getPassword()));
456
+ $customer->save();
457
+ $quote->setCustomer($customer);
458
+
459
+ return $this;
460
+ }
461
+
462
+ /**
463
+ * Prepare quote for customer order submit
464
+ * +/
465
+ * @return Kash_Gateway_Model_Checkout
466
+ */
467
+ protected function _prepareCustomerQuote()
468
+ {
469
+ $quote = $this->_quote;
470
+ $billing = $quote->getBillingAddress();
471
+ $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress();
472
+
473
+ $customer = $this->getCustomerSession()->getCustomer();
474
+ if (!$billing->getCustomerId() || $billing->getSaveInAddressBook()) {
475
+ $customerBilling = $billing->exportCustomerAddress();
476
+ $customer->addAddress($customerBilling);
477
+ $billing->setCustomerAddress($customerBilling);
478
+ }
479
+ if ($shipping && ((!$shipping->getCustomerId() && !$shipping->getSameAsBilling())
480
+ || (!$shipping->getSameAsBilling() && $shipping->getSaveInAddressBook()))
481
+ ) {
482
+ $customerShipping = $shipping->exportCustomerAddress();
483
+ $customer->addAddress($customerShipping);
484
+ $shipping->setCustomerAddress($customerShipping);
485
+ }
486
+
487
+ if (isset($customerBilling) && !$customer->getDefaultBilling()) {
488
+ $customerBilling->setIsDefaultBilling(true);
489
+ }
490
+ if ($shipping && isset($customerBilling) && !$customer->getDefaultShipping() && $shipping->getSameAsBilling()) {
491
+ $customerBilling->setIsDefaultShipping(true);
492
+ } elseif ($shipping && isset($customerShipping) && !$customer->getDefaultShipping()) {
493
+ $customerShipping->setIsDefaultShipping(true);
494
+ }
495
+ $quote->setCustomer($customer);
496
+
497
+ return $this;
498
+ }
499
+
500
+ /**
501
+ * Involve new customer to system
502
+ *
503
+ * @return $this
504
+ */
505
+ protected function _involveNewCustomer()
506
+ {
507
+ $customer = $this->_quote->getCustomer();
508
+ if ($customer->isConfirmationRequired()) {
509
+ $customer->sendNewAccountEmail('confirmation');
510
+ $url = Mage::helper('customer')->getEmailConfirmationUrl($customer->getEmail());
511
+ $this->getCustomerSession()->addSuccess(
512
+ Mage::helper('customer')->__('Account confirmation is required. Please, check your e-mail for confirmation link. To resend confirmation email please <a href="%s">click here</a>.', $url)
513
+ );
514
+ } else {
515
+ $customer->sendNewAccountEmail();
516
+ $this->getCustomerSession()->loginById($customer->getId());
517
+ }
518
+ return $this;
519
+ }
520
+
521
+ /**
522
+ * Get customer session object
523
+ * +/
524
+ * @return Mage_Customer_Model_Session
525
+ */
526
+ public function getCustomerSession()
527
+ {
528
+ return $this->_customerSession;
529
+ }
530
+
531
+ /**
532
+ * Params response
533
+ *
534
+ * @param null $key
535
+ * @return mixed
536
+ */
537
+ public function getParams($key = null)
538
+ {
539
+ if ($key) {
540
+ return array_key_exists($key, $this->_params) ? $this->_params[$key] : null;
541
+ }
542
+ return $this->_params;
543
+ }
544
+
545
+ /**
546
+ * Params response
547
+ *
548
+ * @param mixed $params
549
+ */
550
+ public function setParams($params)
551
+ {
552
+ $this->_params = $params;
553
+ }
554
+
555
+ /**
556
+ * Check gateway signing mechanism
557
+ *
558
+ * @return string
559
+ */
560
+ public function checkSignature()
561
+ {
562
+ $api = $this->_getApi();
563
+ $signature = $this->getParams('x_signature');
564
+ $sig = $api->getSignature($this->getParams(), $api->getHmacKey());
565
+ if ($sig === $signature) {
566
+ return true;
567
+ }
568
+ return false;
569
+ }
570
+
571
+ /**
572
+ * Check result completed|failed|pending ​
573
+ *
574
+ * @return bool
575
+ */
576
+ public function checkResult()
577
+ {
578
+ $xResult = $this->getParams('x_result');
579
+ switch ($xResult) {
580
+ case 'completed':
581
+ return true;
582
+ default:
583
+ return false;
584
+ }
585
+ }
586
+
587
+
588
+ /**
589
+ * Apply Discount
590
+ */
591
+ public function _applyDiscount()
592
+ {
593
+ $xAmount = $this->getParams('x_amount');
594
+ $shippingAmount = $this->_quote->getShippingAddress()->getBaseShippingAmount();
595
+
596
+ $xAmount = $xAmount - $shippingAmount;
597
+ $grandTotal = $this->_quote->getGrandTotal() - $shippingAmount;
598
+
599
+ $percent = round((100 - $xAmount * 100 / $grandTotal), 2);
600
+
601
+ $this->_quote->setCouponCode($this->_getCouponCode($percent));
602
+ }
603
+
604
+ /**
605
+ * Get coupon
606
+ * @param $percent
607
+ * @return string code
608
+ */
609
+ protected function _getCouponCode($percent)
610
+ {
611
+ try {
612
+ $coupon = Mage::getModel('salesrule/coupon')->loadByCode(Kash_Gateway_Model_Config::GATEWAY_KASH_DISCOUNT_CODE);
613
+ if (!$coupon->isEmpty()) {
614
+ $ruleCoupon = Mage::getModel('salesrule/rule')->load($coupon->getRuleId(), 'rule_id');
615
+ if (!$ruleCoupon->isEmpty()) {
616
+ $ruleCoupon->setDiscountAmount($percent);
617
+ $ruleCoupon->save();
618
+ return $ruleCoupon->getCouponCode();
619
+ }
620
+ }
621
+ //when no discount
622
+ $coupon = Mage::getModel('salesrule/coupon')->loadByCode(Kash_Gateway_Model_Config::GATEWAY_KASH_DISCOUNT_CODE);
623
+ if (!$coupon->isEmpty()) {
624
+ $ruleCoupon = Mage::getModel('salesrule/rule')->load($coupon->getRuleId(), 'rule_id');
625
+ $ruleCoupon->delete();
626
+ $coupon->delete();
627
+ }
628
+ $ruleCoupon = Mage::getModel('salesrule/rule');
629
+ $ruleCoupon->setName('Discount for Kash Gateway')
630
+ ->setDescription('this is a discount for the kash gateway')
631
+ ->setFromDate(date('Y-m-d'))
632
+ ->setCouponType(2)
633
+ ->setCouponCode(Kash_Gateway_Model_Config::GATEWAY_KASH_DISCOUNT_CODE)
634
+ ->setCustomerGroupIds(array(1))
635
+ ->setIsActive(1)
636
+ ->setStopRulesProcessing(0)
637
+ ->setIsAdvanced(1)
638
+ ->setProductIds('')
639
+ ->setSortOrder(0)
640
+ ->setSimpleAction('by_percent')
641
+ ->setDiscountAmount($percent)
642
+ ->setDiscountQty(null)
643
+ ->setDiscountStep('0')
644
+ ->setSimpleFreeShipping('0')
645
+ ->setApplyToShipping('0')
646
+ ->setIsRss(0)
647
+ ->setWebsiteIds(array(1));
648
+ $ruleCoupon->save();
649
+ return $ruleCoupon->getCouponCode();
650
+ } catch (Exception $ex) {
651
+ Mage::logException($ex);
652
+ //Mage::throwException($ex);
653
+ }
654
+ }
655
+ }
app/code/local/Kash/Gateway/Model/Config.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Config model that is aware of all Kash_Gateway methods
5
+ * Works with Payment BB system configuration
6
+ *
7
+ * @author Blue Badger <jonathan@badger.blue>
8
+ */
9
+ class Kash_Gateway_Model_Config
10
+ {
11
+ /**
12
+ * Config path for enabling/disabling order review step in express checkout
13
+ */
14
+ const XML_PATH_GATEWAY_KASH_SKIP_ORDER_REVIEW_STEP_FLAG = 'payment/kash_gateway/skip_order_review_step';
15
+
16
+ /**
17
+ * Website Payments Pro - BB Checkout
18
+ * @var string
19
+ */
20
+ const METHOD_GATEWAY_KASH = 'kash_gateway';
21
+
22
+ /**
23
+ * URL for get request - BB Checkout
24
+ * @var string
25
+ */
26
+ const REQUEST_GATEWAY_KASH = 'gateway/bb/getRequest';
27
+
28
+ /**
29
+ * Discount code
30
+ */
31
+ const GATEWAY_KASH_DISCOUNT_CODE ='discount_gatewaykash';
32
+
33
+ /**
34
+ * Current payment method code
35
+ * @var string
36
+ */
37
+ protected $_methodCode = null;
38
+
39
+ /**
40
+ * Current store id
41
+ *
42
+ * @var int
43
+ */
44
+ protected $_storeId = null;
45
+
46
+ /**
47
+ * Set method and store id, if specified
48
+ *
49
+ * @param array $params
50
+ */
51
+ public function __construct($params = array())
52
+ {
53
+ if ($params) {
54
+ $method = array_shift($params);
55
+ $this->setMethod($method);
56
+ if ($params) {
57
+ $storeId = array_shift($params);
58
+ $this->setStoreId($storeId);
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Method code setter +/
65
+ *
66
+ * @param string|Mage_Payment_Model_Method_Abstract $method
67
+ * @return Kash_Gateway_Model_Config
68
+ */
69
+ public function setMethod($method)
70
+ {
71
+ if ($method instanceof Mage_Payment_Model_Method_Abstract) {
72
+ $this->_methodCode = $method->getCode();
73
+ } elseif (is_string($method)) {
74
+ $this->_methodCode = $method;
75
+ }
76
+ return $this;
77
+ }
78
+
79
+ /**
80
+ * Payment method instance code getter +/
81
+ *
82
+ * @return string
83
+ */
84
+ public function getMethodCode()
85
+ {
86
+ return $this->_methodCode;
87
+ }
88
+
89
+ /**
90
+ * Store ID setter
91
+ *
92
+ * @param int $storeId
93
+ * @return Kash_Gateway_Model_Config
94
+ */
95
+ public function setStoreId($storeId)
96
+ {
97
+ $this->_storeId = (int)$storeId;
98
+ return $this;
99
+ }
100
+
101
+
102
+ /**
103
+ * Config field magic getter +/
104
+ * The specified key can be either in camelCase or under_score format
105
+ * Tries to map specified value according to set payment method code, into the configuration value
106
+ * Sets the values into public class parameters, to avoid redundant calls of this method
107
+ *
108
+ * @param string $key
109
+ * @return string|null
110
+ */
111
+ public function __get($key)
112
+ {
113
+ $underscored = strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $key));
114
+ $value = Mage::getStoreConfig($this->_mapMethodFieldset($underscored), $this->_storeId);
115
+ $this->$key = $value;
116
+ $this->$underscored = $value;
117
+ return $value;
118
+ }
119
+
120
+ /**
121
+ * Map Payment BB General Settings
122
+ * +/
123
+ * @param string $fieldName
124
+ * @return string|null
125
+ */
126
+ protected function _mapMethodFieldset($fieldName)
127
+ {
128
+ if (!$this->_methodCode) {
129
+ return null;
130
+ }
131
+ switch ($fieldName) {
132
+ case 'merchant_country':
133
+ return "paypal/general/{$fieldName}";
134
+ case 'post_url':
135
+ case 'x_account_id':
136
+ case 'server_key':
137
+ if (Mage::getStoreConfig($this->_mapMethodFieldset('x_test'), $this->_storeId)) {
138
+ $fieldName .= '_test';
139
+ }
140
+ return "payment/{$this->_methodCode}/{$fieldName}";
141
+ default:
142
+ return "payment/{$this->_methodCode}/{$fieldName}";
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Return merchant country code, use default country if it not specified in General settings
148
+ * +/
149
+ * @return string
150
+ */
151
+ public function getMerchantCountry()
152
+ {
153
+ $countryCode = Mage::getStoreConfig($this->_mapMethodFieldset('merchant_country'), $this->_storeId);
154
+ if (!$countryCode) {
155
+ $countryCode = Mage::helper('core')->getDefaultCountry($this->_storeId);
156
+ }
157
+ return $countryCode;
158
+ }
159
+
160
+ /**
161
+ * Check whether order review step enabled in configuration
162
+ *
163
+ * @return bool
164
+ */
165
+ public function isOrderReviewStepDisabled()
166
+ {
167
+ return Mage::getStoreConfigFlag(self::XML_PATH_GATEWAY_KASH_SKIP_ORDER_REVIEW_STEP_FLAG);
168
+ }
169
+
170
+ /**
171
+ * Get Payment image URL
172
+ * Supposed to be used on payment methods selection
173
+ * $staticSize is applicable for static images only
174
+ *
175
+ * @param string $localeCode
176
+ * @return String
177
+ */
178
+ public function getPaymentImageUrl($localeCode)
179
+ {
180
+ return 'https://offsite-gateway-sim.herokuapp.com/shopify.png';
181
+ }
182
+ }
183
+
app/code/local/Kash/Gateway/Model/Method/Bb.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /** *
4
+ * Payment BB Module
5
+ *
6
+ * @author Blue Badger <jonathan@badger.blue>
7
+ */
8
+ class Kash_Gateway_Model_Method_Bb extends Mage_Payment_Model_Method_Abstract
9
+ {
10
+ protected $_code = Kash_Gateway_Model_Config::METHOD_GATEWAY_KASH;
11
+ protected $_formBlockType = 'kash_gateway/form_bb';
12
+ protected $_infoBlockType = 'kash_gateway/adminhtml_info';
13
+
14
+ protected $_canUseInternal = false;
15
+
16
+ /**
17
+ * Config instance
18
+ *
19
+ * @var Kash_Gateway_Model_Config
20
+ */
21
+ protected $_config = null;
22
+
23
+ /**
24
+ * Config model type
25
+ *
26
+ * @var string
27
+ */
28
+ protected $_configType = 'kash_gateway/config';
29
+
30
+ public function __construct()
31
+ {
32
+ $this->_config = Mage::getModel($this->_configType, array($this->_code));
33
+ }
34
+
35
+ /**
36
+ * Config instance setter
37
+ *
38
+ * @param Kash_Gateway_Model_Config $instace
39
+ * @param int $storeId
40
+ * @return $this
41
+ */
42
+ public function setConfig(Kash_Gateway_Model_Config $instace, $storeId = null)
43
+ {
44
+ $this->_config = $instace;
45
+ if (null !== $storeId) {
46
+ $this->_config->setStoreId($storeId);
47
+ }
48
+ return $this;
49
+ }
50
+
51
+ /**
52
+ * Config instance getter
53
+ *
54
+ * @return Kash_Gateway_Model_Config
55
+ */
56
+ public function getConfig()
57
+ {
58
+ return $this->_config;
59
+ }
60
+
61
+
62
+ /**
63
+ * Store setter
64
+ * Also updates store ID in config object
65
+ *
66
+ * @param Mage_Core_Model_Store|int $store
67
+ * @return Kash_Gateway_Model_Method_Bb
68
+ */
69
+ public function setStore($store)
70
+ {
71
+ $this->setData('store', $store);
72
+ if (null === $store) {
73
+ $store = Mage::app()->getStore()->getId();
74
+ }
75
+ $this->_config->setStoreId(is_object($store) ? $store->getId() : $store);
76
+ return $this;
77
+ }
78
+
79
+ /**
80
+ * Custom getter for payment configuration
81
+ *
82
+ * @param string $field
83
+ * @param int $storeId
84
+ * @return mixed
85
+ */
86
+ public function getConfigData($field, $storeId = null)
87
+ {
88
+ return $this->_config->$field;
89
+ }
90
+
91
+ /**
92
+ * Checkout redirect URL getter for onepage checkout (hardcode)
93
+ *
94
+ * @see Mage_Checkout_OnepageController::savePaymentAction()
95
+ * @see Mage_Sales_Model_Quote_Payment::getCheckoutRedirectUrl()
96
+ * @return string
97
+ */
98
+ public function getCheckoutRedirectUrl()
99
+ {
100
+ return Mage::getUrl('kash_gateway/bb/start', array('_secure'=>true));
101
+ }
102
+
103
+ /**
104
+ * Whether can get recurring profile details
105
+ */
106
+ public function canGetRecurringProfileDetails()
107
+ {
108
+ return true;
109
+ }
110
+
111
+ }
app/code/local/Kash/Gateway/Model/Observer.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Kash_Gateway_Model_Observer extends Varien_Object
4
+ {
5
+ /**
6
+ * Do not show discount in admin panel
7
+ *
8
+ * @param Varien_Object $observer
9
+ * @return Mage_Centinel_Model_Observer
10
+ */
11
+ public function coreCollectionAbstractLoadBefore($observer)
12
+ {
13
+ if (Mage::app()->getRequest()->getRouteName() == 'adminhtml' &&
14
+ Mage::app()->getRequest()->getControllerName() == 'promo_quote'
15
+ ) {
16
+ if ($observer->getCollection() instanceof Mage_SalesRule_Model_Resource_Rule_Collection) {
17
+ $select = $observer->getCollection()->getSelect();
18
+ $select->where('code NOT IN (?)', Kash_Gateway_Model_Config::GATEWAY_KASH_DISCOUNT_CODE);
19
+ $select->orWhere('code IS NULL');
20
+ }
21
+ }
22
+ return $this;
23
+ }
24
+
25
+ /**
26
+ * Do not take the coupon with frontend for customers
27
+ *
28
+ * @param Varien_Object $observer
29
+ * @return Mage_Centinel_Model_Observer
30
+ */
31
+ public function salesQuoteCollectTotalsBefore($observer)
32
+ {
33
+ $quote = $observer->getQuote();
34
+ $discount = $quote->getCouponCode();
35
+ if ($discount === Kash_Gateway_Model_Config::GATEWAY_KASH_DISCOUNT_CODE) {
36
+ $params = Mage::app()->getRequest()->getParams();
37
+ $param = array_key_exists('coupon_code', $params) ? $params['coupon_code'] : null;
38
+ if (Mage::app()->getRequest()->getRouteName() == 'checkout' ||
39
+ $param == $discount) {
40
+ $quote->setCouponCode('');
41
+ }
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Add payment data to info block
47
+ *
48
+ * @param Varien_Object $observer
49
+ * @return Mage_Centinel_Model_Observer
50
+ */
51
+ public function paymentInfoBlockPrepareSpecificInformation($observer)
52
+ {
53
+ if ($observer->getEvent()->getBlock()->getIsSecureMode()) {
54
+ return;
55
+ }
56
+
57
+ $order = $observer->getEvent()->getPayment()->getOrder();
58
+ $discountAmount = abs($order->getDiscountAmount());
59
+ $subtotal = $order->getSubtotal();
60
+
61
+ $percent = round($discountAmount * 100 / $subtotal, 2);
62
+ $transport = $observer->getEvent()->getTransport();
63
+ $transport->setData('Gateway percent', $percent . '%');
64
+
65
+ return $this;
66
+ }
67
+ }
68
+
app/code/local/Kash/Gateway/Model/Session.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Payment transaction session namespace
4
+ */
5
+ class Kash_Gateway_Model_Session extends Mage_Core_Model_Session_Abstract
6
+ {
7
+ public function __construct()
8
+ {
9
+ $this->init('payment');
10
+ }
11
+ }
app/code/local/Kash/Gateway/controllers/BbController.php ADDED
@@ -0,0 +1,448 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Bb Checkout Controller
5
+ *
6
+ * @author Blue Badger <jonathan@badger.blue>
7
+ */
8
+ class Kash_Gateway_BbController extends Mage_Core_Controller_Front_Action
9
+ {
10
+ /**
11
+ * @var Kash_Gateway_Model_Checkout
12
+ */
13
+ protected $_checkout = null;
14
+
15
+ /**
16
+ * Checkout mode type
17
+ *
18
+ * @var string
19
+ */
20
+ protected $_checkoutType = 'kash_gateway/checkout';
21
+
22
+ /**
23
+ * @var Kash_Gateway_Model_Config
24
+ */
25
+ protected $_config = null;
26
+
27
+ /**
28
+ * Config mode type
29
+ *
30
+ * @var string
31
+ */
32
+ protected $_configType = 'kash_gateway/config';
33
+
34
+ /**
35
+ * @var Mage_Sales_Model_Quote
36
+ */
37
+ protected $_quote = false;
38
+
39
+ /**
40
+ * Config method type
41
+ *
42
+ * @var string
43
+ */
44
+ protected $_configMethod = Kash_Gateway_Model_Config::METHOD_GATEWAY_KASH;
45
+
46
+ /**
47
+ * Instantiate config
48
+ */
49
+ protected function _construct()
50
+ {
51
+ parent::_construct();
52
+ $this->_config = Mage::getModel($this->_configType, array($this->_configMethod));
53
+ }
54
+
55
+ /**
56
+ * Get form for requesting form
57
+ */
58
+ public function startAction(){
59
+ $paymentParams = $this->getPaymentRequest();
60
+ if(!$paymentParams){
61
+ return;
62
+ }
63
+ $this->_initToken($paymentParams);
64
+ $this->loadLayout();
65
+ $contentBlock = $this->getLayout()->getBlock('content');
66
+ $formBlock = $contentBlock->getChild('block.form.request');
67
+ $formBlock->setInput($paymentParams);
68
+ $formBlock->setPostUrl($this->_config->post_url);
69
+ $this->renderLayout();
70
+ }
71
+
72
+ /**
73
+ * Get form for requesting initial token and dispatching customer
74
+ */
75
+ public function getRequestAction()
76
+ {
77
+ try {
78
+ $paymentParams = $this->getPaymentRequest();
79
+ if(!$paymentParams){
80
+ return;
81
+ }
82
+ $this->_initToken($paymentParams);
83
+
84
+ $this->loadLayout();
85
+ $block = $this->getLayout()->createBlock(
86
+ 'Mage_Core_Block_Template',
87
+ 'block_form_request',
88
+ array('template' => 'kash/form.phtml')
89
+ );
90
+ $block->setInput($paymentParams);
91
+ $block->setPostUrl($this->_config->post_url);
92
+ $this->getResponse()->setBody($block->toHtml());
93
+ return;
94
+ } catch (Mage_Core_Exception $e) {
95
+ $this->_getCheckoutSession()->addError($e->getMessage());
96
+ } catch (Exception $e) {
97
+ $this->_getCheckoutSession()->addError($this->__('Unable to start BB Checkout.'));
98
+ Mage::logException($e);
99
+ }
100
+
101
+ $this->_redirect('checkout/cart');
102
+ }
103
+
104
+ /**
105
+ * Cancel Payment
106
+ */
107
+ public function cancelAction()
108
+ {
109
+ $this->_initToken(false);
110
+ $this->_redirect('checkout/cart');
111
+ }
112
+
113
+ /**
114
+ * Callback Payment
115
+ */
116
+ public function callbackAction()
117
+ {
118
+ $param = Mage::app()->getRequest()->getParam('x_reference');
119
+ $quota = Mage::getModel('sales/quote')->load($param, 'reserved_order_id');
120
+ $this->_quote = $quota;
121
+
122
+ $this->_config->setStoreId($this->_getQuote()->getStoreId());
123
+ $this->_checkout = Mage::getSingleton($this->_checkoutType, array(
124
+ 'config' => $this->_config,
125
+ 'quote' => $quota,
126
+ ));
127
+
128
+ $params = Mage::app()->getRequest()->getParams();
129
+ $this->_checkout->setParams($params);
130
+
131
+ if ($this->_checkout->checkSignature() &&
132
+ $this->_checkout->checkResult() &&
133
+ $quota->getIsActive()
134
+ ) {
135
+ $this->_checkout->place();
136
+ $order = $this->_checkout->getOrder();
137
+ $this->invoiceOrder($order);
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Complete from Payment and dispatch customer to order review page
143
+ */
144
+ public function completeAction()
145
+ {
146
+ try {
147
+ if (!$this->_initCheckout()) {
148
+ $this->getResponse()->setRedirect(Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB));
149
+ return;
150
+ }
151
+ if (!$this->_checkout->checkSignature()) {
152
+ Mage::log('All requests and responses must be signed/verified using HMAC-SHA256');
153
+ Mage::getSingleton('checkout/session')->addError('Not valid signature');
154
+ $this->_redirect('checkout/cart');
155
+ return;
156
+ }
157
+ if (!$this->_checkout->checkResult()) {
158
+ Mage::log('Result not completed');
159
+ Mage::getSingleton('checkout/session')->addError('Kash Gateway not completed');
160
+ $this->_redirect('checkout/cart');
161
+ return;
162
+ }
163
+
164
+ $this->placeOrder();
165
+ if (!$this->_checkout->canSkipOrderReviewStep()) {
166
+ $this->_redirect('checkout/onepage/success');
167
+ } else {
168
+ $this->_redirect('*/*/review');
169
+ }
170
+ return;
171
+ } catch (Mage_Core_Exception $e) {
172
+ Mage::getSingleton('checkout/session')->addError($e->getMessage());
173
+ } catch (Exception $e) {
174
+ Mage::getSingleton('checkout/session')->addError($this->__('Unable to process Kash Gateway Checkout approval.'));
175
+ Mage::logException($e);
176
+ }
177
+ $this->_redirect('checkout/cart');
178
+ }
179
+
180
+ /**
181
+ * Review order after returning from Payment
182
+ */
183
+ public function reviewAction()
184
+ {
185
+ try {
186
+ $session = $this->_getCheckoutSession();
187
+ // "last successful quote"
188
+ $quoteId = $session->getLastQuoteId();
189
+ $quota = Mage::getModel('sales/quote')->load($quoteId);
190
+
191
+ $this->loadLayout();
192
+ $this->_initLayoutMessages('kash_gateway/session');
193
+ $reviewBlock = $this->getLayout()->getBlock('gateway.kash.review');
194
+ $reviewBlock->setQuote($quota);
195
+ $detailsBlock = $reviewBlock->getChild('details')->setCustomQuote($quota);
196
+ if ($reviewBlock->getChild('shipping_method')) {
197
+ $reviewBlock->getChild('shipping_method')->setCustomQuote($quota);
198
+ }
199
+ if ($detailsBlock->getChild('totals')) {
200
+ $detailsBlock->getChild('totals')->setCustomQuote($quota);
201
+ }
202
+ $this->renderLayout();
203
+ return;
204
+ } catch (Mage_Core_Exception $e) {
205
+ Mage::getSingleton('checkout/session')->addError($e->getMessage());
206
+ } catch (Exception $e) {
207
+ Mage::getSingleton('checkout/session')->addError(
208
+ $this->__('Unable to initialize Kash Gateway Checkout review.')
209
+ );
210
+ Mage::logException($e);
211
+ }
212
+ $this->_redirect('checkout/cart');
213
+ }
214
+
215
+ /**
216
+ * Submit the order
217
+ */
218
+ protected function placeOrder()
219
+ {
220
+ try {
221
+ $this->_initToken();
222
+ $this->_checkout->place();
223
+
224
+ // prepare session to success or cancellation page
225
+ $session = $this->_getCheckoutSession();
226
+ $session->clearHelperData();
227
+
228
+ // "last successful quote"
229
+ $quoteId = $this->_getQuote()->getId();
230
+ $session->setLastQuoteId($quoteId)
231
+ ->setLastSuccessQuoteId($quoteId);
232
+
233
+ // an order may be created
234
+ $order = $this->_checkout->getOrder();
235
+ $this->invoiceOrder($order);
236
+ if ($order) {
237
+ $session->setLastOrderId($order->getId())
238
+ ->setLastRealOrderId($order->getIncrementId());
239
+ }
240
+
241
+ // redirect if Payment specified some URL
242
+ $url = $this->_checkout->getRedirectUrl();
243
+ if ($url) {
244
+ $this->getResponse()->setRedirect($url);
245
+ return;
246
+ }
247
+ $this->_initToken(false); // no need in token anymore
248
+ return;
249
+ } catch (Mage_Core_Exception $e) {
250
+ Mage::helper('checkout')->sendPaymentFailedEmail($this->_getQuote(), $e->getMessage());
251
+ $this->_getSession()->addError($e->getMessage());
252
+ $this->_redirect('*/*/review');
253
+ } catch (Exception $e) {
254
+ Mage::helper('checkout')->sendPaymentFailedEmail(
255
+ $this->_getQuote(),
256
+ $this->__('Unable to place the order.')
257
+ );
258
+ $this->_getSession()->addError($this->__('Unable to place the order.'));
259
+ Mage::logException($e);
260
+ $this->_redirect('*/*/review');
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Auto invoice for order
266
+ *
267
+ * @param $order Mage_Sales_Model_Order
268
+ */
269
+ protected function invoiceOrder($order)
270
+ {
271
+ if ($order->getState() == Mage_Sales_Model_Order::STATE_NEW) {
272
+ try {
273
+ if (!$order->canInvoice()) {
274
+ $order->addStatusHistoryComment('Kash Gateway: Order cannot be auto invoiced.', false);
275
+ $order->save();
276
+ }
277
+ $invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice();
278
+
279
+ $invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
280
+ $invoice->register();
281
+
282
+ $invoice->getOrder()->setCustomerNoteNotify(false);
283
+ $invoice->getOrder()->setIsInProcess(true);
284
+ $order->addStatusHistoryComment('Automatically INVOICED by Kash Gateway.', false);
285
+
286
+ $transactionSave = Mage::getModel('core/resource_transaction')
287
+ ->addObject($invoice)
288
+ ->addObject($invoice->getOrder());
289
+
290
+ $transactionSave->save();
291
+ } catch (Exception $e) {
292
+ $order->addStatusHistoryComment('Kash Gateway: Exception occurred during automatically Invoice action. Exception message: ' . $e->getMessage(), false);
293
+ $order->save();
294
+ }
295
+
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Search for proper checkout token in request or session or (un)set specified one
301
+ * Combined getter/setter
302
+ *
303
+ * @param string $setToken
304
+ * @return $this|mixed|null|string
305
+ */
306
+ protected function _initToken($setToken = null)
307
+ {
308
+ if (null !== $setToken) {
309
+ if (false === $setToken) {
310
+ // security measure for avoid unsetting token twice
311
+ if (!$this->_getSession()->getBBCheckoutToken()) {
312
+ Mage::throwException($this->__('Payment Kash Gateway Checkout Token does not exist.'));
313
+ }
314
+ $this->_getSession()->unsBBCheckoutToken();
315
+ } else {
316
+ $this->_getSession()->setBBCheckoutToken($setToken['x_reference']);
317
+ }
318
+ return $this;
319
+ }
320
+ if ($setToken = $this->getRequest()->getParam('x_reference')) {
321
+ if ($setToken !== $this->_getSession()->getBBCheckoutToken()) {
322
+ Mage::throwException($this->__('Wrong Payment Kash Gateway Checkout Token specified.'));
323
+ }
324
+ } else {
325
+ $setToken = $this->_getSession()->getBBCheckoutToken();
326
+ }
327
+ return $setToken;
328
+ }
329
+
330
+ /**
331
+ * Payment session instance getter
332
+ *
333
+ * @return Kash_Gateway_Model_Session
334
+ */
335
+ protected function _getSession()
336
+ {
337
+ return Mage::getSingleton('kash_gateway/session');
338
+ }
339
+
340
+ /**
341
+ * Return checkout session object
342
+ *
343
+ * @return Mage_Checkout_Model_Session
344
+ */
345
+ protected function _getCheckoutSession()
346
+ {
347
+ return Mage::getSingleton('checkout/session');
348
+ }
349
+
350
+ /**
351
+ * Return checkout quote object
352
+ *
353
+ * @return Mage_Sales_Model_Quote
354
+ */
355
+ private function _getQuote()
356
+ {
357
+ if (!$this->_quote) {
358
+ $this->_quote = $this->_getCheckoutSession()->getQuote();
359
+ }
360
+ return $this->_quote;
361
+ }
362
+
363
+ /**
364
+ * Redirect to login page
365
+ *
366
+ */
367
+ public function redirectLogin()
368
+ {
369
+ $this->setFlag('', 'no-dispatch', true);
370
+ $this->getResponse()->setRedirect(
371
+ Mage::helper('core/url')->addRequestParam(
372
+ Mage::helper('customer')->getLoginUrl(),
373
+ array('context' => 'checkout')
374
+ )
375
+ );
376
+ }
377
+
378
+
379
+ /**
380
+ * Instantiate quote and checkout
381
+ *
382
+ * @param bool $callback
383
+ * @return Kash_Gateway_Model_Checkout
384
+ * @throws Mage_Core_Exception
385
+ */
386
+ protected function _initCheckout($callback = false)
387
+ {
388
+ $quote = $this->_getQuote();
389
+ if (!$callback && (!$quote->hasItems() || $quote->getHasError())) {
390
+ //$this->getResponse()->setHeader('HTTP/1.1', '403 Forbidden');
391
+ Mage::log(Mage::helper('kash_gateway')->__('Unable to initialize Kash Gateway Checkout.'));
392
+ return null;
393
+ }
394
+ $this->_config->setStoreId($this->_getQuote()->getStoreId());
395
+ $this->_checkout = Mage::getSingleton($this->_checkoutType, array(
396
+ 'config' => $this->_config,
397
+ 'quote' => $quote,
398
+ ));
399
+
400
+ $params = Mage::app()->getRequest()->getParams();
401
+ $this->_checkout->setParams($params);
402
+ return $this->_checkout;
403
+ }
404
+
405
+ /**
406
+ * Make params for Payment BB
407
+ */
408
+ protected function getPaymentRequest(){
409
+ $this->_initCheckout();
410
+
411
+ if ($this->_getQuote()->getIsMultiShipping()) {
412
+ $this->_getQuote()->setIsMultiShipping(false);
413
+ $this->_getQuote()->removeAllAddresses();
414
+ }
415
+
416
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
417
+ $quoteCheckoutMethod = $this->_getQuote()->getCheckoutMethod();
418
+ if ($customer && $customer->getId()) {
419
+ $this->_checkout->setCustomerWithAddressChange(
420
+ $customer, $this->_getQuote()->getBillingAddress(), $this->_getQuote()->getShippingAddress()
421
+ );
422
+ } elseif ((!$quoteCheckoutMethod
423
+ || $quoteCheckoutMethod != Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER)
424
+ && !Mage::helper('checkout')->isAllowedGuestCheckout(
425
+ $this->_getQuote(),
426
+ $this->_getQuote()->getStoreId()
427
+ )
428
+ ) {
429
+ Mage::getSingleton('core/session')->addNotice(
430
+ Mage::helper('kash_gateway')->__('To proceed to Checkout, please log in using your email address.')
431
+ );
432
+ $this->redirectLogin();
433
+ Mage::getSingleton('customer/session')
434
+ ->setBeforeAuthUrl(Mage::getUrl('*/*/*', array('_current' => true, '_secure'=>true)));
435
+ return null;
436
+ }
437
+
438
+ // giropay
439
+ $this->_checkout->prepareGiropayUrls(
440
+ Mage::getUrl('gateway/bb/callback', array('_secure'=>true)),
441
+ Mage::getUrl('gateway/bb/cancel', array('_secure'=>true)),
442
+ Mage::getUrl('gateway/bb/complete', array('_secure'=>true))
443
+ );
444
+
445
+ $params = $this->_checkout->start();
446
+ return $params;
447
+ }
448
+ }
app/code/local/Kash/Gateway/data/kash_gateway_setup/data-install-0.0.1.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* @var $installer Mage_Core_Model_Resource_Setup */
4
+ $installer = $this;
5
+
6
+ $installer->startSetup();
7
+
8
+
9
+
10
+ $installer->endSetup();
app/code/local/Kash/Gateway/data/kash_gateway_setup/data-upgrade-0.0.1-0.0.2.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* @var $installer Mage_Core_Model_Resource_Setup */
4
+ $installer = $this;
5
+
6
+ $installer->startSetup();
7
+
8
+ try{
9
+ $coupon = Mage::getModel('salesrule/coupon')->loadByCode(Kash_Gateway_Model_Config::GATEWAY_KASH_DISCOUNT_CODE);
10
+ if(!$coupon->isEmpty()){
11
+ $ruleCoupon = Mage::getModel('salesrule/rule')->load($coupon->getRuleId(), 'rule_id');
12
+ $ruleCoupon->delete();
13
+ $coupon->delete();
14
+ }
15
+ $ruleCoupon = Mage::getModel('salesrule/rule');
16
+ $ruleCoupon->setName('Discount for Payment BB')
17
+ ->setDescription('this is a discount for payment bb')
18
+ ->setFromDate(date('Y-m-d'))
19
+ ->setCouponType(2)
20
+ ->setCouponCode(Kash_Gateway_Model_Config::GATEWAY_KASH_DISCOUNT_CODE)
21
+ ->setCustomerGroupIds(array(1))
22
+ ->setIsActive(1)
23
+ ->setStopRulesProcessing(0)
24
+ ->setIsAdvanced(1)
25
+ ->setProductIds('')
26
+ ->setSortOrder(0)
27
+ ->setSimpleAction('by_percent')
28
+ //->setDiscountAmount(100)
29
+ ->setDiscountQty(null)
30
+ ->setDiscountStep('0')
31
+ ->setSimpleFreeShipping('0')
32
+ ->setApplyToShipping('0')
33
+ ->setIsRss(0)
34
+ ->setWebsiteIds(array(1));
35
+ $ruleCoupon->save();
36
+ }catch (Exception $ex){
37
+ Mage::logException($ex);
38
+ }
39
+
40
+ $installer->endSetup();
app/code/local/Kash/Gateway/etc/config.xml ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Kash_Gateway>
5
+ <version>0.1.1</version>
6
+ </Kash_Gateway>
7
+ </modules>
8
+ <global>
9
+ <models>
10
+ <kash_gateway>
11
+ <class>Kash_Gateway_Model</class>
12
+ <resourceModel>kash_gateway_resource</resourceModel>
13
+ </kash_gateway>
14
+ <kash_gateway_resource>
15
+ <class>Kash_Gateway_Model_Resource</class>
16
+ </kash_gateway_resource>
17
+ </models>
18
+ <blocks>
19
+ <kash_gateway>
20
+ <class>Kash_Gateway_Block</class>
21
+ </kash_gateway>
22
+ <adminhtml>
23
+ <rewrite>
24
+ <sales_order_grid>Kash_Gateway_Block_Adminhtml_Sales_Order_Grid</sales_order_grid>
25
+ </rewrite>
26
+ </adminhtml>
27
+ </blocks>
28
+ <helpers>
29
+ <kash_gateway>
30
+ <class>Kash_Gateway_Helper</class>
31
+ </kash_gateway>
32
+ </helpers>
33
+ <resources>
34
+ <kash_gateway_setup>
35
+ <setup>
36
+ <module>Kash_Gateway</module>
37
+ </setup>
38
+ </kash_gateway_setup>
39
+ </resources>
40
+ <fieldsets>
41
+ <sales_convert_quote_payment>
42
+ <x_gateway_reference>
43
+ <to_order_payment>*</to_order_payment>
44
+ </x_gateway_reference>
45
+ </sales_convert_quote_payment>
46
+ </fieldsets>
47
+ </global>
48
+
49
+ <frontend>
50
+ <layout>
51
+ <updates>
52
+ <kash_gateway>
53
+ <file>kash/gateway.xml</file>
54
+ </kash_gateway>
55
+ </updates>
56
+ </layout>
57
+ </frontend>
58
+
59
+ <adminhtml>
60
+ <events>
61
+ <core_collection_abstract_load_before>
62
+ <observers>
63
+ <kash_gateway>
64
+ <type>model</type>
65
+ <class>kash_gateway/observer</class>
66
+ <method>coreCollectionAbstractLoadBefore</method>
67
+ </kash_gateway>
68
+ </observers>
69
+ </core_collection_abstract_load_before>
70
+ <payment_info_block_prepare_specific_information>
71
+ <observers>
72
+ <kash_gateway>
73
+ <type>model</type>
74
+ <class>kash_gateway/observer</class>
75
+ <method>paymentInfoBlockPrepareSpecificInformation</method>
76
+ </kash_gateway>
77
+ </observers>
78
+ </payment_info_block_prepare_specific_information>
79
+ </events>
80
+ </adminhtml>
81
+
82
+ <default>
83
+ <payment>
84
+ <kash_gateway>
85
+ <active>0</active>
86
+ <bbtypes>AE,VI,MC,DI</bbtypes>
87
+ <model>kash_gateway/method_bb</model>
88
+ <order_status>processing</order_status>
89
+ <title>Direct Debit or Credit Card</title>
90
+ <post_url>https://gateway.withkash.com/</post_url>
91
+ <skip_order_review_step>0</skip_order_review_step>
92
+ <allowspecific>0</allowspecific>
93
+ </kash_gateway>
94
+ </payment>
95
+ </default>
96
+
97
+ <frontend>
98
+ <routers>
99
+ <kash_gateway>
100
+ <use>standard</use>
101
+ <args>
102
+ <module>Kash_Gateway</module>
103
+ <frontName>gateway</frontName>
104
+ </args>
105
+ </kash_gateway>
106
+ </routers>
107
+ <events>
108
+ <sales_quote_collect_totals_before>
109
+ <observers>
110
+ <kash_gateway>
111
+ <type>model</type>
112
+ <class>kash_gateway/observer</class>
113
+ <method>salesQuoteCollectTotalsBefore</method>
114
+ </kash_gateway>
115
+ </observers>
116
+ </sales_quote_collect_totals_before>
117
+ </events>
118
+ </frontend>
119
+ </config>
app/code/local/Kash/Gateway/etc/system.xml ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <sections>
4
+ <payment>
5
+ <groups>
6
+ <kash_gateway translate="label">
7
+ <label>Kash Gateway</label>
8
+ <frontend_type>text</frontend_type>
9
+ <sort_order>30</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>10</sort_order>
27
+ <show_in_default>1</show_in_default>
28
+ <show_in_website>1</show_in_website>
29
+ <show_in_store>1</show_in_store>
30
+ <comment>This controls the title that the user sees during checkout</comment>
31
+ </title>
32
+ <x_shop_name translate="label">
33
+ <label>Shop Name</label>
34
+ <frontend_type>text</frontend_type>
35
+ <sort_order>10</sort_order>
36
+ <show_in_default>1</show_in_default>
37
+ <show_in_website>1</show_in_website>
38
+ <show_in_store>1</show_in_store>
39
+ <frontend_class>required-entry</frontend_class>
40
+ </x_shop_name>
41
+ <x_account_id translate="label">
42
+ <label>Kash Account ID</label>
43
+ <frontend_type>text</frontend_type>
44
+ <frontend_class>required-entry</frontend_class>
45
+ <sort_order>11</sort_order>
46
+ <show_in_default>1</show_in_default>
47
+ <show_in_website>1</show_in_website>
48
+ <show_in_store>1</show_in_store>
49
+ <comment>This is the account ID you get from your Kash account</comment>
50
+ </x_account_id>
51
+ <server_key translate="label">
52
+ <label>Kash Server Key</label>
53
+ <frontend_type>text</frontend_type>
54
+ <frontend_class>required-entry</frontend_class>
55
+ <sort_order>12</sort_order>
56
+ <show_in_default>1</show_in_default>
57
+ <show_in_website>1</show_in_website>
58
+ <show_in_store>1</show_in_store>
59
+ <comment>This is the server key you get from your Kash account</comment>
60
+ </server_key>
61
+ <post_url translate="label">
62
+ <label>Gateway URL</label>
63
+ <frontend_type>text</frontend_type>
64
+ <frontend_class>required-entry</frontend_class>
65
+ <sort_order>14</sort_order>
66
+ <show_in_default>1</show_in_default>
67
+ <show_in_website>1</show_in_website>
68
+ <show_in_store>1</show_in_store>
69
+ <comment>Add a payment gateway with "Redirect URL" of https://offsite-gateway-sim.herokuapp.com/</comment>
70
+ </post_url>
71
+ <skip_order_review_step translate="label comment">
72
+ <label>Order Review Step</label>
73
+ <config_path>payment/kash_gateway/skip_order_review_step</config_path>
74
+ <frontend_type>select</frontend_type>
75
+ <source_model>adminhtml/system_config_source_yesno</source_model>
76
+ <sort_order>25</sort_order>
77
+ <show_in_default>1</show_in_default>
78
+ <show_in_website>1</show_in_website>
79
+ <show_in_store>1</show_in_store>
80
+ <shared>1</shared>
81
+ </skip_order_review_step>
82
+ <min_order_total translate="label">
83
+ <label>Minimum Order Total</label>
84
+ <frontend_type>text</frontend_type>
85
+ <sort_order>98</sort_order>
86
+ <show_in_default>1</show_in_default>
87
+ <show_in_website>1</show_in_website>
88
+ <show_in_store>1</show_in_store>
89
+ </min_order_total>
90
+ <max_order_total translate="label">
91
+ <label>Maximum Order Total</label>
92
+ <frontend_type>text</frontend_type>
93
+ <sort_order>99</sort_order>
94
+ <show_in_default>1</show_in_default>
95
+ <show_in_website>1</show_in_website>
96
+ <show_in_store>1</show_in_store>
97
+ </max_order_total>
98
+ <sort_order translate="label">
99
+ <label>Sort Order</label>
100
+ <frontend_type>text</frontend_type>
101
+ <sort_order>100</sort_order>
102
+ <show_in_default>1</show_in_default>
103
+ <show_in_website>1</show_in_website>
104
+ <show_in_store>1</show_in_store>
105
+ <frontend_class>validate-number</frontend_class>
106
+ </sort_order>
107
+ <model>
108
+ </model>
109
+ </fields>
110
+ </kash_gateway>
111
+ </groups>
112
+ </payment>
113
+ </sections>
114
+ </config>
app/code/local/Kash/Gateway/sql/kash_gateway_setup/install-0.0.1.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* @var $installer Mage_Core_Model_Resource_Setup */
4
+ $installer = $this;
5
+
6
+ $installer->startSetup();
7
+
8
+ $installer->getConnection()
9
+ ->addColumn($installer->getTable('sales/quote_payment'), 'x_gateway_reference', array(
10
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
11
+ 'comment' => 'Gateway Reference',
12
+ 'length' => '255'
13
+ ));
14
+
15
+ $installer->getConnection()
16
+ ->addColumn($installer->getTable('sales/order_payment'), 'x_gateway_reference', array(
17
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
18
+ 'comment' => 'Gateway Reference',
19
+ 'length' => '255'
20
+ ));
21
+
22
+ $installer->endSetup();
app/design/adminhtml/default/default/template/kash/info/default.phtml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @see Kash_Gateway_Block_Adminhtml_Info
4
+ */
5
+ ?>
6
+ <?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?>
7
+
8
+
9
+ <table>
10
+ <?php if ($_specificInfo = $this->getAdditionalInformation()): ?>
11
+ <?php foreach ($_specificInfo as $_label => $_value): ?>
12
+ <tr>
13
+ <td><?php echo $this->escapeHtml($_label) ?>:</td>
14
+ <td><?php echo nl2br(implode($this->getValueAsArray($_value, true), "\n")) ?></td>
15
+ </tr>
16
+ <?php endforeach; ?>
17
+ <?php endif; ?>
18
+
19
+ <?php if ($_specificInfo = $this->getSpecificInformation()): ?>
20
+ <?php foreach ($_specificInfo as $_label => $_value): ?>
21
+ <tr>
22
+ <td><?php echo $this->escapeHtml($_label) ?>:</td>
23
+ <td><?php echo nl2br(implode($this->getValueAsArray($_value, true), "\n")) ?></td>
24
+ </tr>
25
+ <?php endforeach; ?>
26
+ <?php endif; ?>
27
+ </table>
28
+
29
+
30
+ <?php echo $this->getChildHtml() ?>
app/design/frontend/base/default/layout/kash/gateway.xml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+ <default>
4
+ <reference name="before_body_end">
5
+ <block type="core/template" template="kash/js.phtml" before="-"/>
6
+ </reference>
7
+ </default>
8
+
9
+ <kash_gateway_bb_start>
10
+ <remove name="before_body_end"/>
11
+ <reference name="head">
12
+ <action method="addJs">
13
+ <script>lib/jquery/jquery-1.10.2.min.js</script>
14
+ </action>
15
+ <action method="addCss"><stylesheet>css/kash/start.css</stylesheet></action>
16
+ </reference>
17
+ <reference name="root">
18
+ <action method="setTemplate">
19
+ <template>page/empty.phtml</template>
20
+ </action>
21
+ <reference name="content">
22
+ <block type="core/template" name="block_form_request" as="block.form.request"
23
+ template="kash/form.phtml"/>
24
+ <block type="core/template" name="container_form" as="container_form"
25
+ template="kash/container.phtml"/>
26
+ </reference>
27
+ </reference>
28
+ </kash_gateway_bb_start>
29
+
30
+ <kash_gateway_bb_review>
31
+ <remove name="right"/>
32
+ <remove name="left"/>
33
+
34
+ <reference name="root">
35
+ <action method="setTemplate">
36
+ <template>page/1column.phtml</template>
37
+ </action>
38
+ </reference>
39
+ <reference name="content">
40
+ <!--<block type="checkout/onepage_success" name="checkout.success" template="checkout/success.phtml"/>-->
41
+ <block type="kash_gateway/review" name="gateway.kash.review" template="kash/payment/review.phtml">
42
+ <block type="kash_gateway/review_details" name="gateway.kash.review.details" as="details"
43
+ template="kash/payment/review/details.phtml">
44
+ <action method="addItemRender">
45
+ <type>default</type>
46
+ <block>checkout/cart_item_renderer</block>
47
+ <template>checkout/onepage/review/item.phtml</template>
48
+ </action>
49
+ <action method="addItemRender">
50
+ <type>grouped</type>
51
+ <block>checkout/cart_item_renderer_grouped</block>
52
+ <template>checkout/onepage/review/item.phtml</template>
53
+ </action>
54
+ <action method="addItemRender">
55
+ <type>configurable</type>
56
+ <block>checkout/cart_item_renderer_configurable</block>
57
+ <template>checkout/onepage/review/item.phtml</template>
58
+ </action>
59
+ <block type="checkout/cart_totals" name="gateway.kash.review.details.totals" as="totals"
60
+ template="checkout/onepage/review/totals.phtml"/>
61
+ </block>
62
+ </block>
63
+ </reference>
64
+ <reference name="head">
65
+ <action method="addItem">
66
+ <type>skin_js</type>
67
+ <name>js/checkout/review.js</name>
68
+ </action>
69
+ </reference>
70
+ <block type="core/text_list" name="additional.product.info"/>
71
+ </kash_gateway_bb_review>
72
+ </layout>
app/design/frontend/base/default/template/kash/container.phtml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ jQuery(document).ready(function() {
3
+ jQuery("#request-gateway-kash").trigger('submit');
4
+ });
5
+ </script>
app/design/frontend/base/default/template/kash/form.phtml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $input = $this->getInput();
3
+ $action = $this->getPostUrl();
4
+ ?>
5
+
6
+ <form id="request-gateway-kash" name="request-gateway-kash" action="<?php echo $action ?>" method="post">
7
+ <div>
8
+ <?php foreach($input as $key => $value): ?>
9
+ <input type="hidden" name="<?php echo $key; ?>" value="<?php echo $value; ?>"/>
10
+ <?php endforeach; ?>
11
+ </div>
12
+ </form>
13
+
app/design/frontend/base/default/template/kash/js.phtml ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $_methodCode = Kash_Gateway_Model_Config::METHOD_GATEWAY_KASH;
3
+ $_urlRequest = Mage::getUrl(Kash_Gateway_Model_Config::REQUEST_GATEWAY_KASH, array('_secure'=>true));
4
+ ?>
5
+ <div id="form-element" style="display: none"></div>
6
+
7
+ <script type="text/javascript">
8
+ //<![CDATA[
9
+ Payment.addMethods({
10
+ save: function () {
11
+ if (checkout.loadWaiting != false) return;
12
+ var validator = new Validation(this.form);
13
+ if (this.validate() && validator.validate()) {
14
+ checkout.setLoadWaiting('payment');
15
+ if (this.currentMethod == '<?php echo $_methodCode ?>') {
16
+ new Ajax.Request(
17
+ payment.saveUrl,
18
+ {
19
+ asynchronous: true,
20
+ method: 'post',
21
+ onSuccess: function (response) {
22
+ new Ajax.Request(
23
+ '<?php echo $_urlRequest ?>',
24
+ {
25
+ asynchronous: true,
26
+ method: 'post',
27
+ onSuccess: function (response) {
28
+ $('form-element').insert(response.responseText);
29
+ jQuery("#request-gateway-kash").trigger('submit');
30
+ },
31
+ onFailure: checkout.ajaxFailure.bind(checkout),
32
+ parameters: Form.serialize(payment.form)
33
+ }
34
+ );
35
+ },
36
+ onFailure: checkout.ajaxFailure.bind(checkout),
37
+ parameters: Form.serialize(this.form)
38
+ });
39
+ } else {
40
+ var request = new Ajax.Request(
41
+ this.saveUrl,
42
+ {
43
+ asynchronous: true,
44
+ method: 'post',
45
+ onComplete: this.onComplete,
46
+ onSuccess: this.onSave,
47
+ onFailure: checkout.ajaxFailure.bind(checkout),
48
+ parameters: Form.serialize(this.form)
49
+ }
50
+ );
51
+ }
52
+ }
53
+ }
54
+ });
55
+ //]]>
56
+ </script>
app/design/frontend/base/default/template/kash/payment/mark.phtml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @see Kash_Gateway_Block_Form_Bb
4
+ */
5
+ ?>
6
+ <?php echo $this->getMessage() ?>
7
+
app/design/frontend/base/default/template/kash/payment/redirect.phtml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @see Kash_Gateway_Block_Form_Bb
4
+ */
5
+ ?>
6
+ <ul class="form-list" id="payment_form_<?php echo $this->getMethodCode() ?>">
7
+ <li class="form-alt"><?php echo $this->getRedirectMessage() ?></li>
8
+ </ul>
app/design/frontend/base/default/template/kash/payment/review.phtml ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /** @var Kash_Gateway_Block_Review */
3
+ ?>
4
+ <div class="page-title">
5
+ <h1><?php echo $this->__('Complete Order') ?></h1>
6
+ </div>
7
+ <?php echo $this->getMessagesBlock()->toHtml() ?>
8
+ <?php if ($this->getShippingAddress()): ?>
9
+ <div class="info-set col2-set">
10
+ <div class="col-1">
11
+ <div class="box">
12
+ <div class="box-title">
13
+ <h3><?php echo $this->__('Shipping Address') ?><span class="separator"><?php if ($this->getCanEditShippingAddress()):?> | </span><a href="<?php echo $this->getEditUrl() ?>"><?php echo $this->__('Edit') ?></a><?php endif;?></h3>
14
+ </div>
15
+ <div class="box-content">
16
+ <address><?php echo $this->renderAddress($this->getShippingAddress())?></address>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ <div class="col-2">
21
+ <div class="box">
22
+ <div class="box-title">
23
+ <h3><?php echo $this->__('Shipping Method') ?></h3>
24
+ </div>
25
+ <div class="box-content">
26
+ <?php if ($this->getCanEditShippingMethod() || !$this->getCurrentShippingRate()):?>
27
+ <?php if ($groups = $this->getShippingRateGroups()):?>
28
+ <?php $currentRate = $this->getCurrentShippingRate(); ?>
29
+ <fieldset>
30
+ <select name="shipping_method" id="shipping_method" style="width:250px;" class="required-entry">
31
+ <?php if (!$currentRate):?>
32
+ <option value=""><?php echo $this->__('Please select a shipping method...') ?></option>
33
+ <?php endif;?>
34
+ <?php foreach ($groups as $code => $rates):?>
35
+ <optgroup label="<?php echo $this->escapeHtml($this->getCarrierName($code)) ?>" style="font-style:normal;">
36
+ <?php foreach ($rates as $rate):?>
37
+ <option value="<?php echo $this->renderShippingRateValue($rate)?>"<?php echo ($currentRate === $rate) ? ' selected="selected"' : '' ;?>>
38
+ <?php echo $this->renderShippingRateOption($rate)?>
39
+ </option>
40
+ <?php endforeach;?>
41
+ </optgroup>
42
+ <?php endforeach;?>
43
+ </select>
44
+ </fieldset>
45
+ <?php endif;?>
46
+ <?php else: ?>
47
+ <p><strong><?php echo $this->renderShippingRateOption($this->getCurrentShippingRate())?></strong></p>
48
+ <?php endif; ?>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <?php endif; ?>
54
+
55
+
56
+ <div class="info-set">
57
+ <div id="details-reload">
58
+ <?php echo $this->getChildHtml('details') ?>
59
+ </div>
60
+ </div>
61
+
62
+ <div class="buttons-set buttons-set-order" id="review-buttons-container">
63
+ <button type="button" id="review_button" onclick="window.location.href='<?php echo Mage::getUrl('checkout/onepage/success'); ?>'" value="<?php echo $this->__('Close') ?>" class="button btn-checkout"><span><span><?php echo $this->__('Close') ?></span></span></button>
64
+ </div>
65
+
app/design/frontend/base/default/template/kash/payment/review/details.phtml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @see Kash_Gateway_Block_Review_Details
4
+ */
5
+ ?>
6
+ <table id="details-table" class="data-table linearize-table">
7
+ <?php if ($this->helper('tax')->displayCartBothPrices()): $colspan = $rowspan = 2; else: $colspan = $rowspan = 1; endif; ?>
8
+ <col />
9
+ <col width="1" />
10
+ <col width="1" />
11
+ <col width="1" />
12
+ <?php if ($this->helper('tax')->displayCartBothPrices()): ?>
13
+ <col width="1" />
14
+ <col width="1" />
15
+ <?php endif; ?>
16
+ <thead>
17
+ <tr>
18
+ <th rowspan="<?php echo $rowspan ?>"><?php echo $this->__('Product') ?></th>
19
+ <th colspan="<?php echo $colspan ?>" class="a-center"><?php echo $this->__('Price') ?></th>
20
+ <th rowspan="<?php echo $rowspan ?>" class="a-center"><?php echo $this->__('Qty') ?></th>
21
+ <th colspan="<?php echo $colspan ?>" class="a-center"><?php echo $this->__('Subtotal') ?></th>
22
+ </tr>
23
+ <?php if ($this->helper('tax')->displayCartBothPrices()): ?>
24
+ <tr>
25
+ <th class="a-right"><?php echo $this->helper('tax')->getIncExcTaxLabel(false) ?></th>
26
+ <th><?php echo $this->helper('tax')->getIncExcTaxLabel(true) ?></th>
27
+ <th class="a-right"><?php echo $this->helper('tax')->getIncExcTaxLabel(false) ?></th>
28
+ <th><?php echo $this->helper('tax')->getIncExcTaxLabel(true) ?></th>
29
+ </tr>
30
+ <?php endif; ?>
31
+ </thead>
32
+ <?php echo $this->getChildHtml('totals'); ?>
33
+ <tbody>
34
+ <?php foreach($this->getItems() as $_item): ?>
35
+ <?php echo $this->getItemHtml($_item) ?>
36
+ <?php endforeach ?>
37
+ </tbody>
38
+ </table>
39
+ <script type="text/javascript">decorateTable('details-table');</script>
app/etc/modules/Kash_Gateway.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Kash_Gateway>
5
+ <active>true</active>
6
+ <codePool>local</codePool>
7
+ <depends>
8
+ <Mage_Payment/>
9
+ </depends>
10
+ </Kash_Gateway>
11
+ </modules>
12
+ </config>
package.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>kash_gateway</name>
4
+ <version>0.1.1</version>
5
+ <stability>stable</stability>
6
+ <license>MITL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Payment gateway that allows customers in the US to make payment via Direct Debit or Credit Card for just 0.5%.</summary>
10
+ <description>Kash (http://www.withkash.com) allows you to accept payments for just 0.5%!&#xD;
11
+ &#xD;
12
+ Kash does this by offering customers the option to pay using their bank account. For customers that don't want to use their bank account to pay, they'll have the option of using credit card instead. You can choose to either charge the credit card processing fee to the customer, or pay for the fee yourself like you do currently.&#xD;
13
+ &#xD;
14
+ You will need a Kash account in order to use this gateway. Please contact info@withkash.com for any questions.</description>
15
+ <notes>v0.1.1 - Initial Release</notes>
16
+ <authors><author><name>Kash Corp.</name><user>withkash</user><email>info@withkash.com</email></author></authors>
17
+ <date>2015-11-04</date>
18
+ <time>06:56:24</time>
19
+ <contents><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><dir name="kash"><file name="start.css" hash="d310d178769035d366ebb2caff9bd4a3"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Kash_Gateway.xml" hash="03365c54da611a023ea2a12c6404c455"/></dir></target><target name="magelocal"><dir name="Kash"><dir><dir name="Gateway"><dir name="Block"><dir name="Adminhtml"><file name="Info.php" hash="186ac575a69755543d649d2174f43474"/><dir name="Sales"><dir name="Order"><file name="Grid.php" hash="757f5028ff98d3c375cf3345675d55b7"/></dir></dir></dir><dir name="Form"><file name="Bb.php" hash="2516cb64469800cfc450710250317d72"/></dir><dir name="Review"><file name="Details.php" hash="9a077c6688f913bd4f9fee74fad68b7e"/></dir><file name="Review.php" hash="a2a24914d577262188c491898c77307e"/></dir><dir name="Helper"><file name="Checkout.php" hash="89863d74391a81e7336073a8c9634ce8"/><file name="Data.php" hash="cc0eb77c1be47e1d4e846033cc2aed9a"/></dir><dir name="Model"><dir name="Api"><file name="Abstract.php" hash="99ed019c3e8e13caf90fa248e608c9ea"/><file name="Bb.php" hash="f1605310d4042b4704577fe2925c2a86"/></dir><file name="Cart.php" hash="ced06fca31abf3fbe20e3e2eb430cfea"/><file name="Checkout.php" hash="cad380737617bc30c2d067d9f42a7b36"/><file name="Config.php" hash="5299275ecc589f56c9bc9c9123e39405"/><dir name="Method"><file name="Bb.php" hash="6cd0683fa597d31d830ae7787b0284cd"/></dir><file name="Observer.php" hash="d7b27c64189811ac66d82cf6dd3841ff"/><file name="Session.php" hash="1778fbe493d2ceb81d8a20b58a21ce3c"/></dir><dir name="controllers"><file name="BbController.php" hash="6349cf80569789e5cedb77370063046e"/></dir><dir name="data"><dir name="kash_gateway_setup"><file name="data-install-0.0.1.php" hash="5fe91e15bc5e6269eadcc50f8991250a"/><file name="data-upgrade-0.0.1-0.0.2.php" hash="632331f77e2238438e1bddfe4c2b82bf"/></dir></dir><dir name="etc"><file name="config.xml" hash="3b9b94e4fdbd9364d0c24fe7306104d5"/><file name="system.xml" hash="6c4da7f0fd0f07f0577fa1aeb0abee25"/></dir><dir name="sql"><dir name="kash_gateway_setup"><file name="install-0.0.1.php" hash="9ecb52ba48345cdbee9ce0fd92d2aff9"/></dir></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="kash"><dir name="info"><file name="default.phtml" hash="79bcf1003e40c03ec35c383ec4ca5236"/></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="kash"><file name="container.phtml" hash="9dafeab90d16b221ab8684990ef62ec3"/><file name="form.phtml" hash="0b4b05f427474b08d1c52cfc09fc3485"/><file name="js.phtml" hash="3a1b1a96fd25b4035f41dbe95633f229"/><dir><dir name="payment"><file name="mark.phtml" hash="01fa231a78eab8c435d6ea2ad508ef56"/><file name="redirect.phtml" hash="9cd530bec26cc5f76ab01cfb57095c32"/><dir name="review"><file name="details.phtml" hash="ff2ad65893e66920a4cc8b098dc397c1"/></dir><file name="review.phtml" hash="ef1d435a2bc0e9daff56594a715bed1a"/></dir></dir></dir></dir><dir name="layout"><dir name="kash"><file name="gateway.xml" hash="21bd19c6bc5830b2998afcc1bb1e1f27"/></dir></dir></dir></dir></dir></target></contents>
20
+ <compatible/>
21
+ <dependencies><required><php><min>5.4.45</min><max>5.6.15</max></php></required></dependencies>
22
+ </package>
skin/frontend/base/default/css/kash/start.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ .kash-gateway-bb-start {
2
+ background-color: rgba(0, 0, 0, 0.87);
3
+ }