PayFast - Version 1.03

Version Notes

- Fix errors with server URLs

Download this release

Release Info

Developer Magento Core Team
Extension PayFast
Version 1.03
Comparing to
See all releases


Version 1.03

app/code/community/PayFast/PayFast/Block/Form.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Form.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * PayFast_PayFast_Block_Form
12
+ */
13
+ class PayFast_PayFast_Block_Form extends Mage_Payment_Block_Form
14
+ {
15
+ // {{{ _construct()
16
+ /**
17
+ * _construct()
18
+ */
19
+ protected function _construct()
20
+ {
21
+ parent::_construct();
22
+ $this->setTemplate( 'payfast/form.phtml' );
23
+ }
24
+ // }}}
25
+ }
app/code/community/PayFast/PayFast/Block/Payment/Info.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Info.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * PayFast_PayFast_Block_Payment_Info
12
+ */
13
+ class PayFast_PayFast_Block_Payment_Info extends Mage_Payment_Block_Info
14
+ {
15
+ // {{{ _prepareSpecificInformation()
16
+ /**
17
+ * _prepareSpecificInformation
18
+ */
19
+ protected function _prepareSpecificInformation( $transport = null )
20
+ {
21
+ $transport = parent::_prepareSpecificInformation( $transport );
22
+ $payment = $this->getInfo();
23
+ $pfInfo = Mage::getModel( 'payfast/info' );
24
+
25
+ if( !$this->getIsSecureMode() )
26
+ $info = $pfInfo->getPaymentInfo( $payment, true );
27
+ else
28
+ $info = $pfInfo->getPublicPaymentInfo( $payment, true );
29
+
30
+ return( $transport->addData( $info ) );
31
+ }
32
+ // }}}
33
+ }
app/code/community/PayFast/PayFast/Block/Request.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Request.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * PayFast_Block_Request
12
+ */
13
+ class PayFast_PayFast_Block_Request extends Mage_Core_Block_Abstract
14
+ {
15
+ // {{{ _toHtml()
16
+ /**
17
+ * _toHtml
18
+ */
19
+ protected function _toHtml()
20
+ {
21
+ $standard = Mage::getModel( 'payfast/standard' );
22
+ $form = new Varien_Data_Form();
23
+ $form->setAction( $standard->getPayFastUrl() )
24
+ ->setId( 'payfast_checkout' )
25
+ ->setName( 'payfast_checkout' )
26
+ ->setMethod( 'POST' )
27
+ ->setUseContainer( true );
28
+
29
+ foreach( $standard->getStandardCheckoutFormFields() as $field=>$value )
30
+ $form->addField( $field, 'hidden', array( 'name' => $field, 'value' => $value, 'size' => 200 ) );
31
+
32
+ $html = '<html><body>';
33
+ $html.= $this->__( 'You will be redirected to PayFast in a few seconds.' );
34
+ $html.= $form->toHtml();
35
+ #echo $html;exit;
36
+ $html.= '<script type="text/javascript">document.getElementById( "payfast_checkout" ).submit();</script>';
37
+ $html.= '</body></html>';
38
+ return $html;
39
+ }
40
+ // }}}
41
+ }
app/code/community/PayFast/PayFast/Helper/Data.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Data.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * PayFast_PayFast_Helper_Data
12
+ */
13
+ class PayFast_PayFast_Helper_Data extends Mage_Payment_Helper_Data
14
+ {
15
+ // {{{ getPendingPaymentStatus()
16
+ /**
17
+ * getPendingPaymentStatus
18
+ */
19
+ public function getPendingPaymentStatus()
20
+ {
21
+ if( version_compare( Mage::getVersion(), '1.4.0', '<' ) )
22
+ return( Mage_Sales_Model_Order::STATE_HOLDED );
23
+ else
24
+ return( Mage_Sales_Model_Order::STATE_PENDING_PAYMENT );
25
+ }
26
+ // }}}
27
+ }
app/code/community/PayFast/PayFast/Model/Info.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Info.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * PayFast_PayFast_Model_Info
12
+ */
13
+ class PayFast_PayFast_Model_Info
14
+ {
15
+ /**
16
+ * Cross-models public exchange keys
17
+ *
18
+ * @var string
19
+ */
20
+ const PAYMENT_STATUS = 'payment_status';
21
+ const M_PAYMENT_ID = 'm_payment_id';
22
+ const PF_PAYMENT_ID = 'pf_payment_id';
23
+ const EMAIL_ADDRESS = 'email_address';
24
+
25
+ /**
26
+ * All payment information map
27
+ *
28
+ * @var array
29
+ */
30
+ protected $_paymentMap = array(
31
+ self::PAYMENT_STATUS => 'payment_status',
32
+ self::M_PAYMENT_ID => 'm_payment_id',
33
+ self::PF_PAYMENT_ID => 'pf_payment_id',
34
+ self::EMAIL_ADDRESS => 'email_address',
35
+ );
36
+
37
+ /**
38
+ * Map of payment information available to customer
39
+ *
40
+ * @var array
41
+ */
42
+ protected $_paymentPublicMap = array(
43
+ 'email_address'
44
+ );
45
+
46
+ /**
47
+ * Rendered payment map cache
48
+ *
49
+ * @var array
50
+ */
51
+ protected $_paymentMapFull = array();
52
+
53
+
54
+ // {{{ getPaymentInfo()
55
+ /**
56
+ * getPaymentInfo
57
+ */
58
+ public function getPaymentInfo( Mage_Payment_Model_Info $payment, $labelValuesOnly = false )
59
+ {
60
+ // Collect PayFast-specific info
61
+ $result = $this->_getFullInfo( array_values( $this->_paymentMap ), $payment, $labelValuesOnly );
62
+
63
+ return( $result );
64
+ }
65
+ // }}}
66
+ // {{{ getPublicPaymentInfo
67
+ /**
68
+ * getPublicPaymentInfo
69
+ */
70
+ public function getPublicPaymentInfo( Mage_Payment_Model_Info $payment, $labelValuesOnly = false )
71
+ {
72
+ return $this->_getFullInfo( $this->_paymentPublicMap, $payment, $labelValuesOnly );
73
+ }
74
+ // }}}
75
+ // {{{
76
+ /**
77
+ * Grab data from source and map it into payment
78
+ *
79
+ * @param array|Varien_Object|callback $from
80
+ * @param Mage_Payment_Model_Info $payment
81
+ */
82
+ public function importToPayment( $from, Mage_Payment_Model_Info $payment )
83
+ {
84
+ Varien_Object_Mapper::accumulateByMap( $from, array($payment, 'setAdditionalInformation'), $this->_paymentMap );
85
+ }
86
+ // }}}
87
+ // {{{ exportFromPayment()
88
+ /**
89
+ * exportFromPayment
90
+ *
91
+ * Grab data from payment and map it into target
92
+ *
93
+ * @param Mage_Payment_Model_Info $payment
94
+ * @param array|Varien_Object|callback $to
95
+ * @param array $map
96
+ * @return array|Varien_Object
97
+ */
98
+ public function &exportFromPayment( Mage_Payment_Model_Info $payment, $to, array $map = null )
99
+ {
100
+ Varien_Object_Mapper::accumulateByMap( array( $payment, 'getAdditionalInformation' ),
101
+ $to, $map ? $map : array_flip( $this->_paymentMap ) );
102
+
103
+ return( $to );
104
+ }
105
+ // }}}
106
+ // {{{ _getFullInfo()
107
+ /**
108
+ * _getFullInfo
109
+ *
110
+ * Render info item
111
+ *
112
+ * @param array $keys
113
+ * @param Mage_Payment_Model_Info $payment
114
+ * @param bool $labelValuesOnly
115
+ */
116
+ protected function _getFullInfo( array $keys, Mage_Payment_Model_Info $payment, $labelValuesOnly )
117
+ {
118
+ $result = array();
119
+
120
+ foreach( $keys as $key )
121
+ {
122
+ if( !isset( $this->_paymentMapFull[$key] ) )
123
+ $this->_paymentMapFull[$key] = array();
124
+
125
+ if( !isset( $this->_paymentMapFull[$key]['label'] ) )
126
+ {
127
+ if( !$payment->hasAdditionalInformation( $key ) )
128
+ {
129
+ $this->_paymentMapFull[$key]['label'] = false;
130
+ $this->_paymentMapFull[$key]['value'] = false;
131
+ }
132
+ else
133
+ {
134
+ $value = $payment->getAdditionalInformation( $key );
135
+ $this->_paymentMapFull[$key]['label'] = $this->_getLabel( $key );
136
+ $this->_paymentMapFull[$key]['value'] = $this->_getValue( $value, $key );
137
+ }
138
+ }
139
+
140
+ if( !empty( $this->_paymentMapFull[$key]['value'] ) )
141
+ {
142
+ if( $labelValuesOnly )
143
+ $result[$this->_paymentMapFull[$key]['label']] = $this->_paymentMapFull[$key]['value'];
144
+ else
145
+ $result[$key] = $this->_paymentMapFull[$key];
146
+ }
147
+ }
148
+
149
+ return( $result );
150
+ }
151
+ // }}}
152
+ // {{{ _getLabel()
153
+ /**
154
+ * _getLabel
155
+ *
156
+ * Get the label for the given key.
157
+ *
158
+ * @param $key String Key to return the label for
159
+ * @return String Label for the given key
160
+ */
161
+ protected function _getLabel( $key )
162
+ {
163
+ // Variable initialization
164
+ $label = '';
165
+
166
+ switch( $key )
167
+ {
168
+ case 'payment_status':
169
+ $label = Mage::helper( 'payfast' )->__( 'Payment Status' ); break;
170
+ case 'm_payment_id':
171
+ $label = Mage::helper( 'payfast' )->__( 'Payment ID' ); break;
172
+ case 'pf_payment_id':
173
+ $label = Mage::helper( 'payfast' )->__( 'PayFast Payment ID' ); break;
174
+ case 'email_address':
175
+ $label = Mage::helper( 'payfast' )->__( 'Email Address' ); break;
176
+ default:
177
+ $label = ''; break;
178
+ }
179
+
180
+ return( $label );
181
+ }
182
+ // }}}
183
+ // {{{ _getValue()
184
+ /**
185
+ * _getValue
186
+ *
187
+ * Get the value for the given key.
188
+ *
189
+ * @param $value String Key to return the label for
190
+ * @param $key String Key to return the label for
191
+ * @return String Label for the given key
192
+ */
193
+ protected function _getValue( $value, $key )
194
+ {
195
+ return( $value );
196
+ }
197
+ // }}}
198
+ }
app/code/community/PayFast/PayFast/Model/Itn.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Itn.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * Mage_Paypal_Model_Itn
12
+ */
13
+ class Mage_Paypal_Model_Itn
14
+ {
15
+ // {{{ getWriteLog()
16
+ /**
17
+ * getWriteLog
18
+ */
19
+ public function getWriteLog( $data )
20
+ {
21
+ $text = "\n";
22
+ $text .= "RESPONSE: From PayFast[". date("Y-m-d H:i:s") ."]"."\n";
23
+
24
+ foreach( $_REQUEST as $key => $val )
25
+ $text .= $key."=>".$val."\n";
26
+
27
+ $file = dirname( dirname( __FILE__ ) ) ."/Logs/notify.txt";
28
+
29
+ $handle = fopen( $file, 'a' );
30
+ fwrite( $handle, $text );
31
+ fclose( $handle );
32
+ }
33
+ // }}}
34
+ }
app/code/community/PayFast/PayFast/Model/Source/Server.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Server.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * PayFast_PayFast_Model_Source_Server
12
+ */
13
+ class PayFast_PayFast_Model_Source_Server
14
+ {
15
+ // {{{ toOptionArray()
16
+ /**
17
+ * toOptionArray
18
+ */
19
+ public function toOptionArray()
20
+ {
21
+ return array(
22
+ array( 'value' => 'test', 'label' => Mage::helper( 'payfast' )->__( 'Test' ) ),
23
+ array( 'value' => 'live', 'label' => Mage::helper( 'payfast' )->__( 'Live' ) ),
24
+ );
25
+ }
26
+ // }}}
27
+ }
app/code/community/PayFast/PayFast/Model/Standard.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Standard.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ /**
11
+ * PayFast_PayFast_Model_Standard
12
+ */
13
+ class PayFast_PayFast_Model_Standard extends Mage_Payment_Model_Method_Abstract
14
+ {
15
+ protected $_code = 'payfast';
16
+ protected $_formBlockType = 'payfast/form';
17
+ protected $_infoBlockType = 'payfast/payment_info';
18
+ protected $_order;
19
+
20
+ protected $_isGateway = true;
21
+ protected $_canAuthorize = true;
22
+ protected $_canCapture = true;
23
+ protected $_canCapturePartial = false;
24
+ protected $_canRefund = false;
25
+ protected $_canVoid = true;
26
+ protected $_canUseInternal = true;
27
+ protected $_canUseCheckout = true;
28
+ protected $_canUseForMultishipping = true;
29
+ protected $_canSaveCc = false;
30
+
31
+ // {{{ getCheckout()
32
+ /**
33
+ * getCheckout
34
+ */
35
+ public function getCheckout()
36
+ {
37
+ return Mage::getSingleton( 'checkout/session' );
38
+ }
39
+ // }}}
40
+ // {{{ getQuote()
41
+ /**
42
+ * getQuote
43
+ */
44
+ public function getQuote()
45
+ {
46
+ return $this->getCheckout()->getQuote();
47
+ }
48
+ // }}}
49
+ // {{{ getQuote()
50
+ /**
51
+ * getQuote
52
+ */
53
+ public function getConfig()
54
+ {
55
+ return Mage::getSingleton( 'payfast/config' );
56
+ }
57
+ // }}}
58
+ // {{{ getOrderPlaceRedirectUrl()
59
+ /**
60
+ * getOrderPlaceRedirectUrl
61
+ */
62
+ public function getOrderPlaceRedirectUrl()
63
+ {
64
+ return Mage::getUrl( 'payfast/redirect/redirect', array( '_secure' => true ) );
65
+ }
66
+ // }}}
67
+ // {{{ getPaidSuccessUrl()
68
+ /**
69
+ * getPaidSuccessUrl
70
+ */
71
+ public function getPaidSuccessUrl()
72
+ {
73
+ return Mage::getUrl( 'payfast/redirect/success', array( '_secure' => true ) );
74
+ }
75
+ // }}}
76
+ // {{{ getPaidCancelUrl()
77
+ /**
78
+ * getPaidCancelUrl
79
+ */
80
+ public function getPaidCancelUrl()
81
+ {
82
+ return Mage::getUrl( 'payfast/redirect/cancel', array( '_secure' => true ) );
83
+ }
84
+ // }}}
85
+ // {{{ getPaidNotifyUrl()
86
+ /**
87
+ * getPaidNotifyUrl
88
+ */
89
+ public function getPaidNotifyUrl()
90
+ {
91
+ return Mage::getUrl( 'payfast/notify', array( '_secure' => true ) );
92
+ }
93
+ // }}}
94
+ // {{{ getRealOrderId()
95
+ /**
96
+ * getRealOrderId
97
+ */
98
+ public function getRealOrderId()
99
+ {
100
+ return Mage::getSingleton( 'checkout/session' )->getLastRealOrderId();
101
+ }
102
+ // }}}
103
+ // {{{ getNumberFormat($number)
104
+ /**
105
+ * getNumberFormat
106
+ */
107
+ public function getNumberFormat( $number )
108
+ {
109
+ return number_format( $number, 2, '.', '' );
110
+ }
111
+ // }}}
112
+ // {{{ getTotalAmount()
113
+ /**
114
+ * getTotalAmount
115
+ */
116
+ public function getTotalAmount( $order )
117
+ {
118
+ if( $this->getConfigData( 'use_store_currency' ) )
119
+ $price = $this->getNumberFormat( $order->getGrandTotal() );
120
+ else
121
+ $price = $this->getNumberFormat( $order->getBaseGrandTotal() );
122
+
123
+ return $price;
124
+ }
125
+ // }}}
126
+ // {{{ getStoreName()
127
+ /**
128
+ * getStoreName
129
+ */
130
+ public function getStoreName()
131
+ {
132
+ $store_info = Mage::app()->getStore();
133
+ return $store_info->getName();
134
+ }
135
+ // }}}
136
+ // {{{ getStandardCheckoutFormFields()
137
+ /**
138
+ * getStandardCheckoutFormFields
139
+ */
140
+ public function getStandardCheckoutFormFields()
141
+ {
142
+ // Variable initialization
143
+ $orderIncrementId = $this->getCheckout()->getLastRealOrderId();
144
+ $order = Mage::getModel( 'sales/order' )->loadByIncrementId( $orderIncrementId );
145
+ $description = '';
146
+
147
+ // If NOT test mode, use normal credentials
148
+ if( $this->getConfigData( 'server' ) == 'live' )
149
+ {
150
+ $merchantId = $this->getConfigData( 'merchant_id' );
151
+ $merchantKey = $this->getConfigData( 'merchant_key' );
152
+ }
153
+ // If test mode, use generic sandbox credentials
154
+ else
155
+ {
156
+ $merchantId = '10000100';
157
+ $merchantKey = '46f0cd694581a';
158
+ }
159
+
160
+ // Create description
161
+ foreach( $order->getAllItems() as $items )
162
+ {
163
+ $totalPrice = $this->getNumberFormat( $items->getQtyOrdered() * $items->getPrice() );
164
+ $description .=
165
+ $this->getNumberFormat( $items->getQtyOrdered() ) .
166
+ ' x '. $items->getName() .
167
+ ' @ '. $order->getOrderCurrencyCode() . $this->getNumberFormat( $items->getPrice() ) .
168
+ ' = '. $order->getOrderCurrencyCode() . $totalPrice .'; ';
169
+ }
170
+ $description .= 'Shipping = '. $order->getOrderCurrencyCode() . $this->getNumberFormat( $order->getShippingAmount() ).';';
171
+ $description .= 'Total = '. $order->getOrderCurrencyCode() . $this->getTotalAmount( $order ).';';
172
+
173
+ // Construct data for the form
174
+ $data = array(
175
+ // Merchant details
176
+ 'merchant_id' => $merchantId,
177
+ 'merchant_key' => $merchantKey,
178
+ 'return_url' => $this->getPaidSuccessUrl(),
179
+ 'cancel_url' => $this->getPaidCancelUrl(),
180
+ 'notify_url' => $this->getPaidNotifyUrl(),
181
+
182
+ // Buyer details
183
+ 'name_first' => $order->getData( 'customer_firstname' ),
184
+ 'name_last' => $order->getData( 'customer_lastname' ),
185
+ 'email_address' => $order->getData( 'customer_email' ),
186
+
187
+ // Item details
188
+ 'item_name' => $this->getStoreName().', Order #'.$this->getRealOrderId(),
189
+ 'item_description' => $description,
190
+ 'amount' => $this->getTotalAmount( $order ),
191
+ 'm_payment_id' => $this->getRealOrderId(),
192
+ 'currency_code' => $order->getOrderCurrencyCode(),
193
+
194
+ // Other
195
+ 'user_agent' => PF_USER_AGENT,
196
+ );
197
+
198
+ return( $data );
199
+ }
200
+ // }}}
201
+ // {{{ initialize()
202
+ /**
203
+ * initialize
204
+ */
205
+ public function initialize( $paymentAction, $stateObject )
206
+ {
207
+ $state = Mage_Sales_Model_Order::STATE_PENDING_PAYMENT;
208
+ $stateObject->setState( $state );
209
+ $stateObject->setStatus( 'pending_payment' );
210
+ $stateObject->setIsNotified( false );
211
+ }
212
+ // }}}
213
+ // {{{ getPayFastUrl()
214
+ /**
215
+ * getPayFastUrl
216
+ *
217
+ * Get URL for form submission to PayFast.
218
+ */
219
+ public function getPayFastUrl()
220
+ {
221
+ switch( $this->getConfigData( 'server' ) )
222
+ {
223
+ case 'test':
224
+ $url = 'https://sandbox.payfast.co.za/eng/process';
225
+ break;
226
+ case 'live':
227
+ default :
228
+ $url = 'https://www.payfast.co.za/eng/process';
229
+ break;
230
+ }
231
+
232
+ return( $url );
233
+ }
234
+ // }}}
235
+ }
app/code/community/PayFast/PayFast/controllers/NotifyController.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NotifyController.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ // Include the PayFast common file
11
+ define( 'PF_DEBUG', ( Mage::getStoreConfig( 'payment/payfast/debugging' ) ? true : false ) );
12
+ include_once( dirname( __FILE__ ) .'/../payfast_common.inc' );
13
+
14
+
15
+ /**
16
+ * PayFast_PayFast_NotifyController
17
+ */
18
+ class PayFast_PayFast_NotifyController extends Mage_Core_Controller_Front_Action
19
+ {
20
+ // {{{ indexAction()
21
+ /**
22
+ * indexAction
23
+ *
24
+ * Instantiate ITN model and pass ITN request to it
25
+ */
26
+ public function indexAction()
27
+ {
28
+ // Variable Initialization
29
+ $pfError = false;
30
+ $pfErrMsg = '';
31
+ $pfData = array();
32
+ $pfHost = ( ( Mage::getStoreConfig( 'payment/payfast/server' ) == 'live' ) ? 'www' : 'sandbox' ) . '.payfast.co.za';
33
+ $pfOrderId = '';
34
+ $pfParamString = '';
35
+
36
+ pflog( 'PayFast ITN call received' );
37
+ pflog( 'Server = '. Mage::getStoreConfig( 'payment/payfast/server' ) );
38
+
39
+ //// Notify PayFast that information has been received
40
+ if( !$pfError )
41
+ {
42
+ header( 'HTTP/1.0 200 OK' );
43
+ flush();
44
+ }
45
+
46
+ //// Get data sent by PayFast
47
+ if( !$pfError )
48
+ {
49
+ pflog( 'Get posted data' );
50
+
51
+ // Posted variables from ITN
52
+ $pfData = pfGetData();
53
+
54
+ pflog( 'PayFast Data: '. print_r( $pfData, true ) );
55
+
56
+ if( $pfData === false )
57
+ {
58
+ $pfError = true;
59
+ $pfErrMsg = PF_ERR_BAD_ACCESS;
60
+ }
61
+ }
62
+
63
+ //// Verify security signature
64
+ if( !$pfError )
65
+ {
66
+ pflog( 'Verify security signature' );
67
+
68
+ // If signature different, log for debugging
69
+ if( !pfValidSignature( $pfData, $pfParamString ) )
70
+ {
71
+ $pfError = true;
72
+ $pfErrMsg = PF_ERR_INVALID_SIGNATURE;
73
+ }
74
+ }
75
+
76
+ //// Verify source IP (If not in debug mode)
77
+ if( !$pfError && !defined( 'PF_DEBUG' ) )
78
+ {
79
+ pflog( 'Verify source IP' );
80
+
81
+ if( !pfValidIP( $_SERVER['REMOTE_ADDR'] ) )
82
+ {
83
+ $pfError = true;
84
+ $pfErrMsg = PF_ERR_BAD_SOURCE_IP;
85
+ }
86
+ }
87
+
88
+ //// Get internal order and verify it hasn't already been processed
89
+ if( !$pfError )
90
+ {
91
+ pflog( "Check order hasn't been processed" );
92
+
93
+ // Load order
94
+ $trnsOrdId = $pfData['m_payment_id'];
95
+ $order = Mage::getModel( 'sales/order' );
96
+ $order->loadByIncrementId( $trnsOrdId );
97
+ $this->_storeID = $order->getStoreId();
98
+
99
+ // Check order is in "pending payment" state
100
+ if( $order->getStatus() !== Mage_Sales_Model_Order::STATE_PENDING_PAYMENT )
101
+ {
102
+ $pfError = true;
103
+ $pfErrMsg = PF_ERR_ORDER_PROCESSED;
104
+ }
105
+ }
106
+
107
+ //// Verify data received
108
+ if( !$pfError )
109
+ {
110
+ pflog( 'Verify data received' );
111
+
112
+ $pfValid = pfValidData( $pfHost, $pfParamString );
113
+
114
+ if( !$pfValid )
115
+ {
116
+ $pfError = true;
117
+ $pfErrMsg = PF_ERR_BAD_ACCESS;
118
+ }
119
+ }
120
+
121
+ //// Check status and update order
122
+ if( !$pfError )
123
+ {
124
+ pflog( 'Check status and update order' );
125
+
126
+ // Successful
127
+ if( $pfData['payment_status'] == "COMPLETE" )
128
+ {
129
+ pflog( 'Order complete' );
130
+
131
+ // Update order additional payment information
132
+ $payment = $order->getPayment();
133
+ $payment->setAdditionalInformation( "payment_status", $pfData['payment_status'] );
134
+ $payment->setAdditionalInformation( "m_payment_id", $pfData['m_payment_id'] );
135
+ $payment->setAdditionalInformation( "pf_payment_id", $pfData['pf_payment_id'] );
136
+ $payment->setAdditionalInformation( "email_address", $pfData['email_address'] );
137
+ $payment->setAdditionalInformation( "amount_fee", $pfData['amount_fee'] );
138
+ $payment->save();
139
+
140
+ // Save invoice
141
+ $this->saveInvoice( $order );
142
+ }
143
+ }
144
+
145
+ // If an error occurred
146
+ if( $pfError )
147
+ {
148
+ pflog( 'Error occurred: '. $pfErrMsg );
149
+
150
+ // TODO: Use Magento structures to send email
151
+ }
152
+ }
153
+ // }}}
154
+ // {{{ saveInvoice()
155
+ /**
156
+ * saveInvoice
157
+ */
158
+ protected function saveInvoice( Mage_Sales_Model_Order $order )
159
+ {
160
+ pflog( 'Saving invoice' );
161
+
162
+ // Check for mail msg
163
+ $invoice = $order->prepareInvoice();
164
+
165
+ $invoice->register()->capture();
166
+ Mage::getModel( 'core/resource_transaction' )
167
+ ->addObject( $invoice )
168
+ ->addObject( $invoice->getOrder() )
169
+ ->save();
170
+ //$invoice->sendEmail();
171
+
172
+ $message = Mage::helper( 'payfast' )->__( 'Notified customer about invoice #%s.', $invoice->getIncrementId() );
173
+ $comment = $order->sendNewOrderEmail()->addStatusHistoryComment( $message )
174
+ ->setIsCustomerNotified( true )
175
+ ->save();
176
+ }
177
+ // }}}
178
+ }
app/code/community/PayFast/PayFast/controllers/RedirectController.php ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * RedirectController.php
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+
10
+ // Include the PayFast common file
11
+ define( 'PF_DEBUG', ( Mage::getStoreConfig( 'payment/payfast/debugging' ) ? true : false ) );
12
+ include_once( dirname( __FILE__ ) .'/../payfast_common.inc' );
13
+
14
+ /**
15
+ * PayFast_PayFast_RedirectController
16
+ */
17
+ class PayFast_PayFast_RedirectController extends Mage_Core_Controller_Front_Action
18
+ {
19
+ protected $_order;
20
+ protected $_WHAT_STATUS = false;
21
+
22
+ // {{{ getOrder()
23
+ /**
24
+ * getOrder
25
+ */
26
+ public function getOrder()
27
+ {
28
+ return( $this->_order );
29
+ }
30
+ // }}}
31
+ // {{{ _expireAjax()
32
+ /**
33
+ * _expireAjax
34
+ */
35
+ protected function _expireAjax()
36
+ {
37
+ if( !Mage::getSingleton( 'checkout/session' )->getQuote()->hasItems() )
38
+ {
39
+ $this->getResponse()->setHeader( 'HTTP/1.1', '403 Session Expired' );
40
+ exit;
41
+ }
42
+ }
43
+ // }}}
44
+ // {{{ _getCheckout()
45
+ /**
46
+ * _getCheckout
47
+ *
48
+ * Get singleton of Checkout Session Model
49
+ *
50
+ * @return Mage_Checkout_Model_Session
51
+ */
52
+ protected function _getCheckout()
53
+ {
54
+ return Mage::getSingleton( 'checkout/session' );
55
+ }
56
+ // }}}
57
+ // {{{ getQuote()
58
+ /**
59
+ * getQuote
60
+ */
61
+ public function getQuote()
62
+ {
63
+ return $this->getCheckout()->getQuote();
64
+ }
65
+ // }}}
66
+ // {{{ getStandard()
67
+ /**
68
+ * getStandard()
69
+ */
70
+ public function getStandard()
71
+ {
72
+ return Mage::getSingleton( 'payfast/standard' );
73
+ }
74
+ // }}}
75
+ // {{{ getConfig()
76
+ /**
77
+ * getConfig
78
+ */
79
+ public function getConfig()
80
+ {
81
+ return $this->getStandard()->getConfig();
82
+ }
83
+ // }}}
84
+ // {{{ _getPendingPaymentStatus()
85
+ /**
86
+ * _getPendingPaymentStatus
87
+ */
88
+ protected function _getPendingPaymentStatus()
89
+ {
90
+ return Mage::helper( 'payfast' )->getPendingPaymentStatus();
91
+ }
92
+ // }}}
93
+ // {{{ redirectAction()
94
+ /**
95
+ * redirectAction
96
+ */
97
+ public function redirectAction()
98
+ {
99
+ pflog( 'Redirecting to PayFast' );
100
+
101
+ try
102
+ {
103
+ $session = Mage::getSingleton( 'checkout/session' );
104
+
105
+ $order = Mage::getModel( 'sales/order' );
106
+ $order->loadByIncrementId( $session->getLastRealOrderId() );
107
+
108
+ if( !$order->getId() )
109
+ Mage::throwException( 'No order for processing found' );
110
+
111
+ if( $order->getState() != Mage_Sales_Model_Order::STATE_PENDING_PAYMENT )
112
+ {
113
+ $order->setState(
114
+ Mage_Sales_Model_Order::STATE_PENDING_PAYMENT,
115
+ $this->_getPendingPaymentStatus(),
116
+ Mage::helper( 'payfast' )->__( 'Customer was redirected to PayFast.' )
117
+ )->save();
118
+ }
119
+
120
+ if( $session->getQuoteId() && $session->getLastSuccessQuoteId() )
121
+ {
122
+ $session->setPayfastQuoteId( $session->getQuoteId() );
123
+ $session->setPayfastSuccessQuoteId( $session->getLastSuccessQuoteId() );
124
+ $session->setPayfastRealOrderId( $session->getLastRealOrderId() );
125
+ $session->getQuote()->setIsActive( false )->save();
126
+ $session->clear();
127
+ }
128
+
129
+ $this->getResponse()->setBody( $this->getLayout()->createBlock( 'payfast/request' )->toHtml() );
130
+ $session->unsQuoteId();
131
+
132
+ return;
133
+ }
134
+ catch( Mage_Core_Exception $e )
135
+ {
136
+ $this->_getCheckout()->addError( $e->getMessage() );
137
+ }
138
+ catch( Exception $e )
139
+ {
140
+ Mage::logException($e);
141
+ }
142
+
143
+ $this->_redirect( 'checkout/cart' );
144
+ }
145
+ // }}}
146
+ // {{{ cancelAction()
147
+ /**
148
+ * cancelAction
149
+ *
150
+ * Action for when a user cancel's a payment on PayFast.
151
+ */
152
+ public function cancelAction()
153
+ {
154
+ // Get the user session
155
+ $session = Mage::getSingleton( 'checkout/session' );
156
+ $session->setQuoteId( $session->getPayfastQuoteId( true ) );
157
+ $session = $this->_getCheckout();
158
+
159
+ if( $quoteId = $session->getPayfastQuoteId() )
160
+ {
161
+ $quote = Mage::getModel( 'sales/quote' )->load( $quoteId );
162
+
163
+ if( $quote->getId() )
164
+ {
165
+ $quote->setIsActive( true )->save();
166
+ $session->setQuoteId( $quoteId );
167
+ }
168
+ }
169
+
170
+ // Cancel order
171
+ $order = Mage::getModel( 'sales/order' )->loadByIncrementId( $session->getLastRealOrderId() );
172
+ if( $order->getId() )
173
+ $order->cancel()->save();
174
+
175
+ $this->_redirect('checkout/cart');
176
+ }
177
+ // }}}
178
+ // {{{ successAction()
179
+ /**
180
+ * successAction
181
+ */
182
+ public function successAction()
183
+ {
184
+ try
185
+ {
186
+ $session = Mage::getSingleton( 'checkout/session' );;
187
+ $session->unsPayfastRealOrderId();
188
+ $session->setQuoteId( $session->getPayfastQuoteId( true ) );
189
+ $session->setLastSuccessQuoteId( $session->getPayfastSuccessQuoteId( true ) );
190
+ $this->_redirect( 'checkout/onepage/success', array( '_secure' => true ) );
191
+
192
+ return;
193
+ }
194
+ catch( Mage_Core_Exception $e )
195
+ {
196
+ $this->_getCheckout()->addError( $e->getMessage() );
197
+ }
198
+ catch( Exception $e )
199
+ {
200
+ Mage::logException( $e );
201
+ }
202
+
203
+ $this->_redirect( 'checkout/cart' );
204
+ }
205
+ // }}}
206
+ }
app/code/community/PayFast/PayFast/etc/config.xml ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ config.xml
4
+
5
+ @category PayFast
6
+ @package PayFast_PayFast
7
+ @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ -->
9
+ <config>
10
+ <modules>
11
+ <PayFast_PayFast>
12
+ <version>0.1.0</version>
13
+ </PayFast_PayFast>
14
+ </modules>
15
+ <global>
16
+ <blocks>
17
+ <payfast>
18
+ <class>PayFast_PayFast_Block</class>
19
+ </payfast>
20
+ </blocks>
21
+ <helpers>
22
+ <payfast>
23
+ <class>PayFast_PayFast_Helper</class>
24
+ </payfast>
25
+ </helpers>
26
+ <models>
27
+ <payfast>
28
+ <class>PayFast_PayFast_Model</class>
29
+ </payfast>
30
+ </models>
31
+ <resources>
32
+ <payfast_setup>
33
+ <setup>
34
+ <module>PayFast_PayFast</module>
35
+ </setup>
36
+ <connection>
37
+ <use>core_setup</use>
38
+ </connection>
39
+ </payfast_setup>
40
+ <newmodule_write>
41
+ <connection>
42
+ <use>core_write</use>
43
+ </connection>
44
+ </newmodule_write>
45
+ <newmodule_read>
46
+ <connection>
47
+ <use>core_read</use>
48
+ </connection>
49
+ </newmodule_read>
50
+ </resources>
51
+ </global>
52
+
53
+ <frontend>
54
+ <routers>
55
+ <payfast>
56
+ <use>standard</use>
57
+ <args>
58
+ <module>PayFast_PayFast</module>
59
+ <frontName>payfast</frontName>
60
+ </args>
61
+ </payfast>
62
+ </routers>
63
+ </frontend>
64
+
65
+ <default>
66
+ <payment>
67
+ <payfast>
68
+ <model>payfast/standard</model>
69
+ <active>0</active>
70
+ <title><![CDATA[PayFast]]></title>
71
+ <server>test</server>
72
+ <debugging>0</debugging>
73
+ </payfast>
74
+ </payment>
75
+ </default>
76
+ </config>
app/code/community/PayFast/PayFast/etc/system.xml ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ system.xml
4
+
5
+ @category PayFast
6
+ @package PayFast_PayFast
7
+ @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ -->
9
+ <config>
10
+ <sections>
11
+ <payment>
12
+ <groups>
13
+ <payfast translate="label" module="payfast">
14
+ <label><![CDATA[PayFast]]></label>
15
+ <sort_order>100</sort_order>
16
+ <show_in_default>1</show_in_default>
17
+ <show_in_website>1</show_in_website>
18
+ <show_in_store>0</show_in_store>
19
+ <fields>
20
+ <active translate="label">
21
+ <label>Enabled</label>
22
+ <frontend_type>select</frontend_type>
23
+ <source_model>adminhtml/system_config_source_yesno</source_model>
24
+ <sort_order>1</sort_order>
25
+ <show_in_default>1</show_in_default>
26
+ <show_in_website>1</show_in_website>
27
+ <show_in_store>0</show_in_store>
28
+ </active>
29
+
30
+ <title translate="label">
31
+ <label>Title</label>
32
+ <frontend_type>text</frontend_type>
33
+ <sort_order>2</sort_order>
34
+ <show_in_default>1</show_in_default>
35
+ <show_in_website>1</show_in_website>
36
+ <show_in_store>0</show_in_store>
37
+ </title>
38
+
39
+ <merchant_id translate="label">
40
+ <label>Merchant ID</label>
41
+ <frontend_type>text</frontend_type>
42
+ <sort_order>3</sort_order>
43
+ <show_in_default>1</show_in_default>
44
+ <show_in_website>1</show_in_website>
45
+ <show_in_store>0</show_in_store>
46
+ </merchant_id>
47
+
48
+ <merchant_key translate="label">
49
+ <label>Merchant Key</label>
50
+ <frontend_type>text</frontend_type>
51
+ <sort_order>4</sort_order>
52
+ <show_in_default>1</show_in_default>
53
+ <show_in_website>1</show_in_website>
54
+ <show_in_store>0</show_in_store>
55
+ </merchant_key>
56
+
57
+ <server translate="label">
58
+ <label>Server</label>
59
+ <frontend_type>select</frontend_type>
60
+ <source_model>payfast/source_server</source_model>
61
+ <sort_order>5</sort_order>
62
+ <show_in_default>1</show_in_default>
63
+ <show_in_website>1</show_in_website>
64
+ <show_in_store>0</show_in_store>
65
+ </server>
66
+
67
+ <debugging translate="label">
68
+ <label>Debugging</label>
69
+ <frontend_type>select</frontend_type>
70
+ <source_model>adminhtml/system_config_source_yesno</source_model>
71
+ <sort_order>6</sort_order>
72
+ <show_in_default>1</show_in_default>
73
+ <show_in_website>1</show_in_website>
74
+ <show_in_store>0</show_in_store>
75
+ </debugging>
76
+
77
+ <debugging_email translate="label">
78
+ <label>Debugging Email</label>
79
+ <frontend_type>select</frontend_type>
80
+ <source_model>adminhtml/system_config_source_yesno</source_model>
81
+ <sort_order>7</sort_order>
82
+ <show_in_default>1</show_in_default>
83
+ <show_in_website>1</show_in_website>
84
+ <show_in_store>0</show_in_store>
85
+ </debugging_email>
86
+ </fields>
87
+ </payfast>
88
+ </groups>
89
+ </payment>
90
+ </sections>
91
+ </config>
app/code/community/PayFast/PayFast/payfast.log ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 2010-09-21 17:11:35 : Redirecting to PayFast
2
+ 2010-09-21 17:14:35 : PayFast ITN call received
3
+ 2010-09-21 17:14:35 : Server = live
4
+ 2010-09-21 17:14:35 : Get posted data
5
+ 2010-09-21 17:14:35 : PayFast Data: Array
6
+ (
7
+ [m_payment_id] => 100000020
8
+ [pf_payment_id] => 211
9
+ [payment_status] => COMPLETE
10
+ [item_name] => Magento Test Store (English), Order #100000020
11
+ [item_description] => 1.00 x Nokia 2610 Phone @ ZAR149.99 = ZAR149.99; Shipping = ZAR5.00;Total = ZAR154.99;
12
+ [amount_gross] => 154.99
13
+ [amount_fee] => -2.00
14
+ [amount_net] => 152.99
15
+ [custom_str1] =>
16
+ [custom_str2] =>
17
+ [custom_str3] =>
18
+ [custom_str4] =>
19
+ [custom_str5] =>
20
+ [custom_int1] =>
21
+ [custom_int2] =>
22
+ [custom_int3] =>
23
+ [custom_int4] =>
24
+ [custom_int5] =>
25
+ [name_first] => Jonathan
26
+ [name_last] => Smit
27
+ [email_address] => jonathan@payfast.co.za
28
+ [merchant_id] => 10000101
29
+ [signature] => 40cd879be9d91cb0764879b4470370eb
30
+ )
31
+
32
+ 2010-09-21 17:14:35 : Verify security signature
33
+ 2010-09-21 17:14:35 : Signature = valid
34
+ 2010-09-21 17:14:35 : Check order hasn't been processed
35
+ 2010-09-21 17:14:35 : Check status and update order
36
+ 2010-09-21 17:14:35 : Order complete
37
+ 2010-09-21 17:14:36 : Saving invoice
app/code/community/PayFast/PayFast/payfast_common.inc ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * common.php
4
+ *
5
+ * @copyright Copyright 2009-2010, PayFast (Pty) Ltd
6
+ * @author Jonathan Smit
7
+ */
8
+ //// Create user agent string
9
+ // User agent constituents (for cURL)
10
+ define( 'PF_SOFTWARE_NAME', 'Magento' );
11
+ define( 'PF_SOFTWARE_VER', Mage::getVersion() );
12
+ define( 'PF_MODULE_NAME', 'PayFast-Magento' );
13
+ define( 'PF_MODULE_VER', '1.00' );
14
+
15
+ // Features
16
+ // - PHP
17
+ $pfFeatures = 'PHP '. phpversion() .';';
18
+
19
+ // - cURL
20
+ if( in_array( 'curl', get_loaded_extensions() ) )
21
+ {
22
+ define( 'PF_CURL', '' );
23
+ $pfVersion = curl_version();
24
+ $pfFeatures .= ' curl '. $pfVersion['version'] .';';
25
+ }
26
+ else
27
+ $pfFeatures .= ' nocurl;';
28
+
29
+ // Create user agrent
30
+ define( 'PF_USER_AGENT', PF_SOFTWARE_NAME .'/'. PF_SOFTWARE_VER .' ('. trim( $pfFeatures ) .') '. PF_MODULE_NAME .'/'. PF_MODULE_VER );
31
+
32
+ // General Defines
33
+ define( 'PF_TIMEOUT', 15 );
34
+ define( 'PF_EPSILON', 0.01 );
35
+
36
+ // Messages
37
+ // Error
38
+ define( 'PF_ERR_AMOUNT_MISMATCH', 'Amount mismatch' );
39
+ define( 'PF_ERR_BAD_ACCESS', 'Bad access of page' );
40
+ define( 'PF_ERR_BAD_SOURCE_IP', 'Bad source IP address' );
41
+ define( 'PF_ERR_CONNECT_FAILED', 'Failed to connect to PayFast' );
42
+ define( 'PF_ERR_INVALID_SIGNATURE', 'Security signature mismatch' );
43
+ define( 'PF_ERR_MERCHANT_ID_MISMATCH', 'Merchant ID mismatch' );
44
+ define( 'PF_ERR_NO_SESSION', 'No saved session found for ITN transaction' );
45
+ define( 'PF_ERR_ORDER_ID_MISSING_URL', 'Order ID not present in URL' );
46
+ define( 'PF_ERR_ORDER_ID_MISMATCH', 'Order ID mismatch' );
47
+ define( 'PF_ERR_ORDER_INVALID', 'This order ID is invalid' );
48
+ define( 'PF_ERR_ORDER_PROCESSED', 'This order has already been processed' );
49
+ define( 'PF_ERR_PDT_FAIL', 'PDT query failed' );
50
+ define( 'PF_ERR_PDT_TOKEN_MISSING', 'PDT token not present in URL' );
51
+ define( 'PF_ERR_SESSIONID_MISMATCH', 'Session ID mismatch' );
52
+ define( 'PF_ERR_UNKNOWN', 'Unkown error occurred' );
53
+
54
+ // General
55
+ define( 'PF_MSG_OK', 'Payment was successful' );
56
+ define( 'PF_MSG_FAILED', 'Payment has failed' );
57
+ define( 'PF_MSG_PENDING',
58
+ 'The payment is pending. Please note, you will receive another Instant'.
59
+ ' Transaction Notification when the payment status changes to'.
60
+ ' "Completed", or "Failed"' );
61
+
62
+ // {{{ pfLog
63
+ /**
64
+ * pflog
65
+ *
66
+ * Log function for logging output.
67
+ *
68
+ * @author Jonathan Smit
69
+ * @param $msg String Message to log
70
+ * @param $close Boolean Whether to close the log file or not
71
+ */
72
+ function pflog( $msg = '', $close = false )
73
+ {
74
+ static $fh = 0;
75
+ global $module;
76
+
77
+ // Only log if debugging is enabled
78
+ if( PF_DEBUG )
79
+ {
80
+ if( $close )
81
+ {
82
+ fclose( $fh );
83
+ }
84
+ else
85
+ {
86
+ // If file doesn't exist, create it
87
+ if( !$fh )
88
+ {
89
+ $pathinfo = pathinfo( __FILE__ );
90
+ $fh = fopen( $pathinfo['dirname'] .'/payfast.log', 'a+' );
91
+ }
92
+
93
+ // If file was successfully created
94
+ if( $fh )
95
+ {
96
+ $line = date( 'Y-m-d H:i:s' ) .' : '. $msg ."\n";
97
+
98
+ fwrite( $fh, $line );
99
+ }
100
+ }
101
+ }
102
+ }
103
+ // }}}
104
+ // {{{ pfGetData
105
+ /**
106
+ * pfGetData
107
+ *
108
+ * @author Jonathan Smit
109
+ */
110
+ function pfGetData()
111
+ {
112
+ // Posted variables from ITN
113
+ $pfData = $_POST;
114
+
115
+ // Strip any slashes in data
116
+ foreach( $pfData as $key => $val )
117
+ $pfData[$key] = stripslashes( $val );
118
+
119
+ // Return "false" if no data was received
120
+ if( sizeof( $pfData ) == 0 )
121
+ return( false );
122
+ else
123
+ return( $pfData );
124
+ }
125
+ // }}}
126
+ // {{{ pfValidSignature
127
+ /**
128
+ * pfValidSignature
129
+ *
130
+ * @author Jonathan Smit
131
+ */
132
+ function pfValidSignature( $pfData = null, &$pfParamString = null )
133
+ {
134
+ // Dump the submitted variables and calculate security signature
135
+ foreach( $pfData as $key => $val )
136
+ {
137
+ if( $key != 'signature' )
138
+ $pfParamString .= $key .'='. urlencode( $val ) .'&';
139
+ }
140
+
141
+ // Remove the last '&' from the parameter string
142
+ $pfParamString = substr( $pfParamString, 0, -1 );
143
+ $signature = md5( $pfParamString );
144
+
145
+ $result = ( $pfData['signature'] == $signature );
146
+
147
+ pflog( 'Signature = '. ( $result ? 'valid' : 'invalid' ) );
148
+
149
+ return( $result );
150
+ }
151
+ // }}}
152
+ // {{{ pfValidData
153
+ /**
154
+ * pfValidData
155
+ *
156
+ * @author Jonathan Smit
157
+ * @param $pfHost String Hostname to use
158
+ * @param $pfParamString String
159
+ */
160
+ function pfValidData( $pfHost = 'www.payfast.co.za', $pfParamString = '' )
161
+ {
162
+ pflog( 'Host = '. $pfHost );
163
+ pflog( 'Params = '. $pfParamString );
164
+
165
+ // Use cURL (if available)
166
+ if( defined( 'PF_CURL' ) )
167
+ {
168
+ // Variable initialization
169
+ $url = 'https://'. $pfHost .'/eng/query/validate';
170
+
171
+ // Create default cURL object
172
+ $ch = curl_init();
173
+
174
+ // Set cURL options - Use curl_setopt for freater PHP compatibility
175
+ // Base settings
176
+ curl_setopt( $ch, CURLOPT_USERAGENT, PF_USER_AGENT ); // Set user agent
177
+ curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); // Return output as string rather than outputting it
178
+ curl_setopt( $ch, CURLOPT_HEADER, false ); // Don't include header in output
179
+ curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, true );
180
+ curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
181
+
182
+ // Standard settings
183
+ curl_setopt( $ch, CURLOPT_URL, $url );
184
+ curl_setopt( $ch, CURLOPT_POST, true );
185
+ curl_setopt( $ch, CURLOPT_POSTFIELDS, $pfParamString );
186
+ curl_setopt( $ch, CURLOPT_TIMEOUT, PF_TIMEOUT );
187
+
188
+ // Execute CURL
189
+ $response = curl_exec( $ch );
190
+ curl_close( $ch );
191
+ }
192
+ // Use fsockopen
193
+ else
194
+ {
195
+ // Variable initialization
196
+ $header = '';
197
+ $res = '';
198
+ $headerDone = false;
199
+
200
+ // Construct Header
201
+ $header = "POST /eng/query/validate HTTP/1.0\r\n";
202
+ $header .= "Host: ". $pfHost ."\r\n";
203
+ $header .= "User-Agent: ". PF_USER_AGENT ."\r\n";
204
+ $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
205
+ $header .= "Content-Length: " . strlen( $pfParamString ) . "\r\n\r\n";
206
+
207
+ // Connect to server
208
+ $socket = fsockopen( 'ssl://'. $pfHost, 443, $errno, $errstr, PF_TIMEOUT );
209
+
210
+ // Send command to server
211
+ fputs( $socket, $header . $pfParamString );
212
+
213
+ // Read the response from the server
214
+ while( !feof( $socket ) )
215
+ {
216
+ $line = fgets( $socket, 1024 );
217
+
218
+ // Check if we are finished reading the header yet
219
+ if( strcmp( $line, "\r\n" ) == 0 )
220
+ {
221
+ // read the header
222
+ $headerDone = true;
223
+ }
224
+ // If header has been processed
225
+ else if( $headerDone )
226
+ {
227
+ // Read the main response
228
+ $response .= $line;
229
+ }
230
+ }
231
+
232
+ }
233
+
234
+ pflog( "Response:\n". print_r( $response, true ) );
235
+
236
+ // Interpret Response
237
+ $lines = explode( "\r\n", $response );
238
+ $verifyResult = trim( $lines[0] );
239
+
240
+ if( strcasecmp( $verifyResult, 'VALID' ) == 0 )
241
+ return( true );
242
+ else
243
+ return( false );
244
+ }
245
+ // }}}
246
+ // {{{ pfValidIP
247
+ /**
248
+ * pfValidIP
249
+ *
250
+ * @author Jonathan Smit
251
+ * @param $sourceIP String Source IP address
252
+ */
253
+ function pfValidIP( $sourceIP )
254
+ {
255
+ // Variable initialization
256
+ $validHosts = array(
257
+ 'www.payfast.co.za',
258
+ 'sandbox.payfast.co.za',
259
+ 'w1w.payfast.co.za',
260
+ 'w2w.payfast.co.za',
261
+ );
262
+
263
+ $validIps = array();
264
+
265
+ foreach( $validHosts as $pfHostname )
266
+ {
267
+ $ips = gethostbynamel( $pfHostname );
268
+
269
+ if( $ips !== false )
270
+ $validIps = array_merge( $validIps, $ips );
271
+ }
272
+
273
+ // Remove duplicates
274
+ $validIps = array_unique( $validIps );
275
+
276
+ pflog( "Valid IPs:\n". print_r( $validIps, true ) );
277
+
278
+ if( in_array( $sourceIP, $validIps ) )
279
+ return( true );
280
+ else
281
+ return( false );
282
+ }
283
+ // }}}
284
+ // {{{ pfAmountsEqual
285
+ /**
286
+ * pfAmountsEqual
287
+ *
288
+ * Checks to see whether the given amounts are equal using a proper floating
289
+ * point comparison with an Epsilon which ensures that insignificant decimal
290
+ * places are ignored in the comparison.
291
+ *
292
+ * eg. 100.00 is equal to 100.0001
293
+ *
294
+ * @author Jonathan Smit
295
+ * @param $amount1 Float 1st amount for comparison
296
+ * @param $amount2 Float 2nd amount for comparison
297
+ */
298
+ function pfAmountsEqual( $amount1, $amount2 )
299
+ {
300
+ if( abs( floatval( $amount1 ) - floatval( $amount2 ) ) > PF_EPSILON )
301
+ return( false );
302
+ else
303
+ return( true );
304
+ }
305
+ // }}}
306
+ ?>
app/design/frontend/default/default/template/payfast/form.phtml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * form.phtml
4
+ *
5
+ * @category PayFast
6
+ * @package PayFast_PayFast
7
+ * @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ */
9
+ ?>
10
+ <fieldset class="form-list">
11
+ <?php $_code=$this->getMethodCode() ?>
12
+ <ul id="payment_form_<?php echo $_code ?>" style="display:none">
13
+ <li>
14
+ <?php echo $this->__('You will be redirected to the PayFast website when you place an order.') ?>
15
+ </li>
16
+ </ul>
17
+ </fieldset>
app/etc/modules/PayFast_PayFast.xml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ config.xml
4
+
5
+ @category PayFast
6
+ @package PayFast_PayFast
7
+ @copyright Copyright (c) 2010 PayFast (Pty) Ltd (http://www.payfast.co.za)
8
+ -->
9
+ <config>
10
+ <modules>
11
+ <PayFast_PayFast>
12
+ <active>true</active>
13
+ <codePool>community</codePool>
14
+ </PayFast_PayFast>
15
+ </modules>
16
+ </config>
package.xml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>PayFast</name>
4
+ <version>1.03</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.gnu.org/licenses/gpl-3.0.txt">GNU General Public License (GPL)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Payment module for PayFast (www.payfast.co.za). Allows your customers to pay via Credit Card, EFT and Ukash.</summary>
10
+ <description>This extension adds PayFast as a payment option on your Magento store.
11
+
12
+ PayFast (www.payfast.co.za) charges no monthly or setup costs. Only per transaction fees.
13
+
14
+ Your customers will be able to pay via Credit Card, Instant EFT and Ukash with more payment methods added in future without any additional work required on your part.
15
+
16
+ Features:
17
+
18
+ - Secure automatic updating of orders within Magento
19
+ - Immune to connection interruptions
20
+ - Email notification of each payment (if desired)
21
+ - Testing server available
22
+ - Debugging and log output to diagnose errors</description>
23
+ <notes>- Fix errors with server URLs</notes>
24
+ <authors><author><name>PayFast</name><user>auto-converted</user><email>jonathan@payfast.co.za</email></author></authors>
25
+ <date>2011-01-25</date>
26
+ <time>12:05:11</time>
27
+ <contents><target name="magedesign"><dir name="frontend"><dir name="default"><dir name="default"><dir name="template"><dir name="payfast"><file name="form.phtml" hash="4c88eee4a75f0f5fe7aa65ee5dd0d73a"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="PayFast_PayFast.xml" hash="c8bf7a6f0d3f6b95b5904124faf8177f"/></dir></target><target name="magecommunity"><dir name="PayFast"><dir name="PayFast"><dir name="Block"><dir name="Payment"><file name="Info.php" hash="9087abccf95bf78c304ac8840426ee12"/></dir><file name="Form.php" hash="30f7690f987e4a750f525bc1e98aaa93"/><file name="Request.php" hash="302e1cf27eca62fd7e794bf3fa210e0c"/></dir><dir name="controllers"><file name="NotifyController.php" hash="eddf555e38336e10e5d271f5227bdf6c"/><file name="RedirectController.php" hash="7f46ec2c84f8431ea102d67d5dbb783d"/></dir><dir name="etc"><file name="config.xml" hash="55f0710e0e3da4f87cf653508b866899"/><file name="system.xml" hash="4b902996f85fba02b78e6e07d2a9bf00"/></dir><dir name="Helper"><file name="Data.php" hash="3d9c06a7237c6df2670e15181b593f53"/></dir><dir name="Model"><dir name="Source"><file name="Server.php" hash="b37d25275dcc36fd1ba7a85bd3eff351"/></dir><file name="Info.php" hash="038ce8d75b2d353ced74e8f4fa7befb7"/><file name="Itn.php" hash="8b161d03799684c290e95aacb9d9fa2f"/><file name="Standard.php" hash="9f5cd1a66479f0a9837295c004b36a6a"/></dir><file name="payfast.log" hash="a941dbe4a6d6594a2e82a0ed284ec2b1"/><file name="payfast_common.inc" hash="4ce2a105b14378a5160fc421151b806c"/></dir></dir></target></contents>
28
+ <compatible/>
29
+ <dependencies/>
30
+ </package>