SHOW:
|
|
- or go back to the newest paste.
1 | <?php | |
2 | /* | |
3 | Plugin Name: EDD PayFast Payment Gateway | |
4 | Plugin URI: http://www.mesaneweb,com | |
5 | Description: Accept payments through PayFast for your Digital Store powered by Easy Digital Downloads, a payment gateway for South Africans. | |
6 | Version: 1.0.1 | |
7 | Author: Dane A. Mesane | |
8 | Author URI: http://www.mesaneweb.com | |
9 | License: GPL version 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
10 | */ | |
11 | /* Copyright 2014 Dane A. Mesane (www.mesaneweb.com) ( email : support@mesaneweb.com ) | |
12 | ||
13 | This program is free software; you can redistribute it and/or modify | |
14 | it under the terms of the GNU General Public License, version 2, as | |
15 | published by the Free Software Foundation. | |
16 | ||
17 | This program is distributed in the hope that it will be useful, | |
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | GNU General Public License for more details. | |
21 | ||
22 | You should have received a copy of the GNU General Public License | |
23 | along with this program; if not, write to the Free Software | |
24 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | //check the existensi of our class and Easy_Digital_Downloads, | |
28 | if( ! class_exists( 'EDD_Payfast' ) ) : | |
29 | ||
30 | class EDD_Payfast { | |
31 | ||
32 | /** | |
33 | * @var instance The one true EDD_Payfast class | |
34 | * singleton | |
35 | */ | |
36 | private static $instance; | |
37 | ||
38 | // Our file of this plugin | |
39 | public $file; | |
40 | ||
41 | // Our plugin path | |
42 | public $plugin_path; | |
43 | ||
44 | // Our plugin url | |
45 | public $plugin_url; | |
46 | ||
47 | // the version of this plugin | |
48 | public $version; | |
49 | ||
50 | /** | |
51 | * Main EDD_Payfast Instance | |
52 | * singleton implementation | |
53 | */ | |
54 | public static function instance() { | |
55 | if ( ! isset( self::$instance ) ) { | |
56 | self::$instance = new EDD_Payfast(__FILE__); | |
57 | } | |
58 | return self::$instance; | |
59 | } | |
60 | /** | |
61 | * Constructor | |
62 | * @since 1.0.0 | |
63 | * @return void | |
64 | */ | |
65 | private function __construct( $file ) { | |
66 | ||
67 | //set up our data | |
68 | $this->version = '1.0.0'; | |
69 | $this->file = $file; | |
70 | $this->plugin_url = trailingslashit( plugins_url( '', $plugin = $file ) ); | |
71 | $this->plugin_path = trailingslashit( dirname( $file ) ); | |
72 | ||
73 | if ( ! function_exists( 'json_decode' ) ) { | |
74 | if ( is_admin() ) | |
75 | add_action( 'admin_notices', array( &$this, 'initialization_warning' ) ); | |
76 | return; | |
77 | } | |
78 | //hooks for admin | |
79 | if( is_admin() ) | |
80 | add_filter( 'edd_settings_gateways', array( &$this, 'add_settings_gateways' ) ); | |
81 | ||
82 | // hooks | |
83 | add_filter( 'edd_currencies', array( &$this, 'rand_currencies' )); //add South African currency, R or ZAR | |
84 | add_filter( 'edd_accepted_payment_icons', array( &$this, 'payfast_payment_icon' ) ); | |
85 | add_filter( 'edd_payment_gateways', array( &$this, 'register_gateway' ) ); | |
86 | add_action( 'edd_payfast_cc_form', array( &$this, 'gateway_cc_form' ) ); | |
87 | add_action( 'edd_gateway_payfast', array( &$this, 'process_payment' ) ); | |
88 | add_action( 'init', array( &$this, 'validate_report_back' ) ); // trying to get notify from payfast | |
89 | add_action( 'edd_payfast_check', array( &$this, 'process_payfast_notify' ) ); | |
90 | ||
91 | } //end __construct | |
92 | ||
93 | /** | |
94 | * Yeah, Because we need json_docode() function to retrieve session ID from Payfast | |
95 | * So if the function don't exists we should throw a warning | |
96 | * | |
97 | * @since 1.0 | |
98 | */ | |
99 | public function initialization_warning() { | |
100 | echo '<div id="edd-payfast-warning" class="updated fade"><p><strong>' . sprintf( __( '%s PHP library not installed.', 'edd-payfast' ), 'JSON' ) . '</strong> '; | |
101 | echo sprintf( __('EDD Payfast Payment Gateway plugin will not function without <a href="%s">PHP JSON functions</a> enabled. Please update your version of WordPress for improved compatibility and/or enable native JSON support for PHP.'), 'http://php.net/manual/book.json.php' ); | |
102 | echo '</p></div>'; | |
103 | } | |
104 | ||
105 | /* in order to disable credit card form that registered by Easy Digital Downloads by default. I return to blank value | |
106 | * on other words, we just registered that. we don't need that for our gateway.. | |
107 | */ | |
108 | public static function gateway_cc_form() { | |
109 | return; | |
110 | } //end gateway_cc_form() | |
111 | ||
112 | /* | |
113 | * add our icon on checkout page | |
114 | * | |
115 | * @return void | |
116 | * @access public | |
117 | * | |
118 | */ | |
119 | ||
120 | public function payfast_payment_icon( $icons ) { | |
121 | $icons[$this->plugin_url . 'assets/images/PayFast.png'] = 'Payfast'; | |
122 | return $icons; | |
123 | } //end payfast_payment_icon() | |
124 | ||
125 | /* | |
126 | * add our currency, sadly South African Rand ( R ) not support on the core of Easy Digital Downloads | |
127 | * but the plugin allow to filter that function | |
128 | * | |
129 | * I don't know why other people called our currency is ZAR, but we familiar with R as our currency | |
130 | * because of that, I set both here... | |
131 | */ | |
132 | function rand_currencies( $currencies ) { | |
133 | ||
134 | $currencies['R'] = __('South African Rand ( R )', 'edd_payfast'); | |
135 | ||
136 | return $currencies; | |
137 | ||
138 | } //end rand_currencies() | |
139 | ||
140 | // Remote get and retrieve respon body.. | |
141 | private function remote_get( $url, $headers = array() ) { | |
142 | ||
143 | $response = wp_remote_get( $url, | |
144 | array( | |
145 | 'redirection' => 1, | |
146 | 'httpversion' => '1.1', | |
147 | 'user-agent' => 'EDD Payfast' . $this->version . '; WordPress (' . home_url( '/' ) . ')', | |
148 | 'timeout' => 15, | |
149 | 'headers' => $headers | |
150 | ) | |
151 | ); | |
152 | ||
153 | if ( !is_wp_error( $response ) && $response['response']['code'] == 200 ) { | |
154 | return $response['body']; | |
155 | } else { | |
156 | return false; | |
157 | } | |
158 | } //end remote_get() | |
159 | ||
160 | // Lets register our gateway, we can use $gateways object because this run during hooks | |
161 | public function register_gateway( $gateways ) { | |
162 | ||
163 | $gateways['payfast'] = array( 'admin_label' => __( 'Payfast', 'edd_payfast' ), 'checkout_label' => __('Payfast', 'edd_payfast')); | |
164 | ||
165 | return $gateways; | |
166 | } | |
167 | ||
168 | /* | |
169 | * Easy Digital Downloads have settings method that allow other developer filter that to add additional settings | |
170 | * So because this plugin is an extension/add on for EDD, we don't need create settings from scratch or create | |
171 | * tradional setting on Wordpress, beautifull.. | |
172 | * | |
173 | * @access public | |
174 | * @return void | |
175 | * @since 0.0.1 | |
176 | */ | |
177 | public function add_settings_gateways( $settings ) { | |
178 | ||
179 | $edd_payfast_settings = array( | |
180 | ||
181 | array( | |
182 | 'id' => '_edd_payfast_gateway_settings', | |
183 | 'name' => '<strong>' . __('Payfast Gateway Settings', 'edd_payfast') . '</strong>', | |
184 | 'desc' => __('Configure the gateway settings', 'edd_payfast'), | |
185 | 'type' => 'header' | |
186 | ), | |
187 | array( | |
188 | 'id' => 'edd_payfast_merchant_id', | |
189 | 'name' => __('Merchant ID', 'pw_edd'), | |
190 | 'desc' => __('Enter your Payfast Merchant ID, you can finf it under settings in your PayFast account. Please click <a https://www.payfast.co.za/acc/integration>here</a>.', 'edd_payfast'), | |
191 | 'type' => 'text', | |
192 | 'size' => 'regular' | |
193 | ), | |
194 | array( | |
195 | 'id' => 'edd_payfast_merchant_key', | |
196 | 'name' => __('Merchant Key', 'pw_edd'), | |
197 | 'desc' => __('Enter your Payfast Merchant Key, you can finf it under settings in your PayFast account. Please click <a https://www.payfast.co.za/acc/integration >here</a>.', 'edd_payfast'), | |
198 | 'type' => 'text', | |
199 | 'size' => 'regular' | |
200 | ) | |
201 | ); | |
202 | ||
203 | return array_merge( $settings, $edd_payfast_settings ); | |
204 | } //end add_settings_gateways() | |
205 | ||
206 | public function process_payment( $purchase_data ) { | |
207 | ||
208 | global $edd_options; | |
209 | ||
210 | // Check there is a gateway name | |
211 | if ( ! isset( $purchase_data['post_data']['edd-gateway'] ) ) | |
212 | return; | |
213 | ||
214 | $errors = edd_get_errors(); | |
215 | ||
216 | if( !$errors ) { | |
217 | ||
218 | $payment_data = array( | |
219 | 'price' => $purchase_data['price'], | |
220 | 'date' => $purchase_data['date'], | |
221 | 'user_email' => $purchase_data['user_email'], | |
222 | 'purchase_key' => $purchase_data['purchase_key'], | |
223 | 'currency' => $edd_options['currency'], | |
224 | 'downloads' => $purchase_data['downloads'], | |
225 | 'user_info' => $purchase_data['user_info'], | |
226 | 'cart_details' => $purchase_data['cart_details'], | |
227 | 'status' => 'pending' | |
228 | ); | |
229 | ||
230 | // record the pending payment | |
231 | $payment = edd_insert_payment( $payment_data ); | |
232 | ||
233 | if ( ! $payment ) { | |
234 | // Record the error | |
235 | edd_record_gateway_error( __( 'Payment Error', 'edd_payfast' ), sprintf( __( 'Payment creation failed before sending buyer to Payfast. Payment data: %s', 'edd_payfast' ), json_encode( $payment_data ) ), $payment ); | |
236 | // Problems? send back | |
237 | edd_send_back_to_checkout( '?payment-mode=' . $purchase_data['post_data']['edd-gateway'] ); | |
238 | ||
239 | } else { | |
240 | ||
241 | $return_url = add_query_arg( 'payment-confirmation', 'payfast', get_permalink( $edd_options['success_page'] ) ); | |
242 | $listener_url = trailingslashit( home_url() ).'?payfast=notify'; | |
243 | $cancel_url = add_query_arg( 'payment-cancel', 'payfast', edd_get_failed_transaction_uri() ); | |
244 | ||
245 | $summary = edd_get_purchase_summary( $purchase_data, false ); | |
246 | $quantity = edd_get_cart_quantity(); | |
247 | - | if ( is_ssl() || ! $ssl_check ) { |
247 | + | |
248 | function edd_get_payfast_redirect( $ssl_check = false ) { | |
249 | global $edd_options; | |
250 | if ( is_ssl() || ! $ssl_check) { | |
251 | $protocal = 'https://'; | |
252 | } else { | |
253 | $protocal = 'http://'; | |
254 | - | $url_to_send = $protocal . 'https://sandbox.payfast.co.za/eng/process'; |
254 | + | |
255 | ||
256 | - | $url_to_send = $protocal . 'https://www.payfast.co.za/eng/process'; |
256 | + | |
257 | $url_to_send = $protocal . 'http://sandbox.payfast.co.za/eng/process'; | |
258 | } else { | |
259 | $url_to_send = $protocal . 'http://www.payfast.co.za/eng/process'; | |
260 | } | |
261 | ||
262 | $payfast_args = array( | |
263 | 'key' => $edd_options['edd_payfast_api_key'], // API Key Merchant / Penjual | |
264 | 'action' => 'payment', | |
265 | 'product' => stripslashes_deep( html_entity_decode( wp_strip_all_tags( $summary ), ENT_COMPAT, 'UTF-8' ) ), | |
266 | 'price' => round( $purchase_data['price'] - $purchase_data['tax'], 2 ), // | |
267 | 'quantity' => $quantity, | |
268 | 'comments' => $payment, // Optional for Payfast, but this is the payment ID, we need it to verify payment | |
269 | 'ureturn' => $return_url, | |
270 | 'unotify' => $listener_url, | |
271 | 'ucancel' => $cancel_url, //if cancel back to check out | |
272 | 'format' => 'json' // Format: xml / json. Default: xml | |
273 | ); | |
274 | ||
275 | //var_dump( add_query_arg( $payfast_args, $url_to_send ) ); exit; | |
276 | $url_to_send .= http_build_query( $payfast_args ); | |
277 | //remote get and retrieve a session id from payfast | |
278 | $response = $this->remote_get( $url_to_send ); | |
279 | ||
280 | if ( $response == null || $response == 'null' ) | |
281 | return false; | |
282 | ||
283 | $payfast = json_decode( $response ); | |
284 | //get the session from payfast, we are ready to send the buyer | |
285 | $session_id = $payfast->sessionID; | |
286 | ||
287 | //save to database first, we will need it | |
288 | add_post_meta( $payment, '_payfast_session_id', $session_id ); | |
289 | ||
290 | //get rid of cart contents | |
291 | edd_empty_cart(); | |
292 | ||
293 | //build an query againt, but we just need session id | |
294 | $params = array( 'sessionID' => $session_id, ); | |
295 | $redirecting_to = add_query_arg( $params, 'https://www.payfast.co.za/' ); | |
296 | //redirect to payfast | |
297 | - | } //end statement payment |
297 | + | |
298 | exit; | |
299 | ||
300 | - | } //end statement error |
300 | + | } //end statement payment |
301 | - | else { |
301 | + | |
302 | - | $fail = true; // errors were detected |
302 | + | |
303 | } //end statement error | |
304 | else { | |
305 | - | if( $fail !== false ) { |
305 | + | $fail = true; // errors were detected |
306 | - | // if errors are present, send the user back to the purchase page so they can be corrected |
306 | + | } //end statement |
307 | - | edd_send_back_to_checkout('?payment-mode=' . $purchase_data['post_data']['edd-gateway']); |
307 | + | |
308 | if( $fail !== false ) { | |
309 | // if errors are present, send the user back to the purchase page so they can be corrected | |
310 | edd_send_back_to_checkout('?payment-mode=' . $purchase_data['post_data']['edd-gateway']); | |
311 | } //end statement | |
312 | ||
313 | } //end process_payment() | |
314 | ||
315 | public function validate_report_back() { | |
316 | global $edd_options; | |
317 | ||
318 | // Regular Payfast notify | |
319 | if ( isset( $_GET['payfast'] ) && $_GET['payfast'] == 'notify' ) { | |
320 | do_action( 'edd_payfast_check' ); | |
321 | } //end statement | |
322 | } //end validate_report_back() | |
323 | ||
324 | /** | |
325 | * Extract the site's host domain for referer notify from payfast. | |
326 | * | |
327 | * @since 1.0 | |
328 | * @param string $url URL to extract | |
329 | * @return host of url that given on param, or false if failed extract url | |
330 | * @access private | |
331 | */ | |
332 | public function check_referer_notify( $url ) { | |
333 | ||
334 | if ( ! ( is_string( $url ) && $url ) ) | |
335 | return false; | |
336 | ||
337 | if ( ! function_exists('parse_url') ) | |
338 | return false; | |
339 | ||
340 | // PHP 5.3.3 or newer can throw a warning | |
341 | try { | |
342 | if ( version_compare( PHP_VERSION, '5.1.2', '>=') ) { | |
343 | $ref = parse_url ( $url, PHP_URL_HOST ); | |
344 | } else { | |
345 | $parse_ref = parse_url( $url ); | |
346 | if ( $parse_ref !== false && isset( $parse_ref['host'] ) ) | |
347 | $ref = $parse_ref['host']; | |
348 | } | |
349 | } catch (Exception $e){} | |
350 | ||
351 | // Check $ref is not empty or null, is so return that. | |
352 | if( empty( $ref ) || $ref = null ) | |
353 | return false; | |
354 | else | |
355 | return $ref; | |
356 | } | |
357 | ||
358 | /* | |
359 | * process_payfast_notify() function | |
360 | * process notify that send by payfast after we send the buyer on payment | |
361 | * | |
362 | * if buyer complete the payment, we need update the payment to complete too | |
363 | * @since 1.0 | |
364 | */ | |
365 | public function process_payfast_notify() { | |
366 | ||
367 | global $edd_options; | |
368 | ||
369 | // Check the request method is POST | |
370 | if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) { | |
371 | return; | |
372 | } //end statement | |
373 | ||
374 | ||
375 | if ( isset( $_POST['status'] ) && isset( $_POST['trx_id'] ) && isset( $_POST['sid'] ) && isset( $_POST['product'] ) && isset( $_POST['quantity'] ) && isset( $_POST['total'] ) && isset( $_POST['comments'] ) ) { | |
376 | ||
377 | // setup each of the variables from payfast | |
378 | $payment_id = $_POST['comments'] ? $_POST['comments'] : null; | |
379 | $payfast_status = strtolower( $_POST['status'] ) ? strtolower( $_POST['status'] ) : null; | |
380 | $payfast_session = $_POST['sid'] ? $_POST['sid'] : null; | |
381 | $payfast_product = $_POST['product'] ? $_POST['product'] : null; | |
382 | $payfast_quantity = $_POST['quantity'] ? $_POST['quantity'] : null; | |
383 | $payfast_amount = $_POST['total'] ? $_POST['total'] : null; | |
384 | ||
385 | // retrieve the meta info for this payment | |
386 | $payment_meta = get_post_meta( $payment_id, '_edd_payment_meta', true ); | |
387 | $payment_session = get_post_meta( $payment_id, '_payfast_session_id', true ); | |
388 | $payment_amount = edd_format_amount( $payment_meta['amount'] ); | |
389 | ||
390 | ||
391 | // check url referrer.. | |
392 | if( ! function_exists( 'wp_get_referer' ) ) | |
393 | include_once( ABSPATH . 'wp-includes/functions.php' ); | |
394 | $referer = wp_get_referer(); | |
395 | if( empty( $referer ) ) | |
396 | return; | |
397 | ||
398 | $ref = $this->check_referer_notify( $referer ); | |
399 | if ( $ref != 'payfast.co.za' ) | |
400 | return; // referrer from payfast? if not return that. | |
401 | ||
402 | if( get_post_status( $payment_id ) == 'complete' ) | |
403 | return; // Only complete payments once | |
404 | ||
405 | if ( edd_get_payment_gateway( $payment_id ) != 'payfast' ) | |
406 | return; // this isn't from payfast | |
407 | ||
408 | if( $payfast_amount != $payment_amount ) | |
409 | return; // the prices don't match | |
410 | ||
411 | // check the session id, this session is an unique key. generating by payfast | |
412 | // if this don't match, this is not from payfast or other payment | |
413 | if( $payfast_session != $payment_session ) | |
414 | return; | |
415 | ||
416 | /* everything has been verified, update the payment to "complete" | |
417 | * berhasil is Indonesian language that mean success. | |
418 | */ | |
419 | if( $payfast_status == 'berhasil' ) : | |
420 | edd_update_payment_status( $payment_id, 'publish' ); | |
421 | delete_post_meta( $payment_id, '_payfast_session_id', $payment_session ); | |
422 | endif; | |
423 | ||
424 | ||
425 | }//end statement | |
426 | ||
427 | } //end process_payfast_notify() | |
428 | ||
429 | ||
430 | } // end EDD_Payfast Class | |
431 | endif; // end check | |
432 | ||
433 | /** | |
434 | * Throw an error if Easy Digital Download is not installed. | |
435 | * | |
436 | * @since 0.2 | |
437 | */ | |
438 | function syaiful_payfast_missing_error_edd() { | |
439 | echo '<div class="error"><p>' . sprintf( __( 'Please %sinstall & activate Easy Digital Downloads%s to allow this plugin to work.' ), '<a href="' . admin_url( 'plugin-install.php?tab=search&type=term&s=easy+digital+downloads&plugin-search-input=Search+Plugins' ) . '">', '</a>' ) . '</p></div>'; | |
440 | } // end syaiful_payfast_missing_error_edd() | |
441 | ||
442 | // Throw an error if Wordpress version is below 3.4 | |
443 | function syaiful_missing_error_wordpress_version() { | |
444 | echo '<div class="error"><p>' . __( 'Please upgrade WordPress to the latest version to allow WordPress and this plugin to work properly.', 'edd_payfast' ) . '</p></div>'; | |
445 | } // end syaiful_missing_error_wordpress_version() | |
446 | ||
447 | // the instance of our plugin, | |
448 | function edd_payfast() { | |
449 | return EDD_Payfast::instance(); | |
450 | } | |
451 | ||
452 | // Loader function for the plugin | |
453 | function syaiful_edd_payfast_init() { | |
454 | global $wp_version; | |
455 | ||
456 | if ( !version_compare( $wp_version, '3.4', '>=' ) ) { | |
457 | add_action( 'all_admin_notices', 'syaiful_missing_error_wordpress_version' ); | |
458 | } else if ( class_exists( 'Easy_Digital_Downloads') ) { | |
459 | edd_payfast(); //load our plugin | |
460 | } else { | |
461 | add_action( 'all_admin_notices', 'syaiful_payfast_missing_error_edd' ); | |
462 | } | |
463 | } // end syaiful_edd_payfast_init() | |
464 | ||
465 | // tap... tap .... hi Wordpress, load our plugin please... | |
466 | add_action( 'plugins_loaded', 'syaiful_edd_payfast_init', 20 ); //lower because waiting Easy Digital Downloads running.. |