Advertisement
dmesane

EDD PayFast

May 4th, 2014
354
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
  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. }
  255.  
  256. if( edd_is_test_mode() ) {
  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. wp_redirect( $redirecting_to );
  298. exit;
  299.  
  300. } //end statement payment
  301.  
  302.  
  303. } //end statement error
  304. else {
  305. $fail = true; // errors were detected
  306. } //end statement
  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 &amp; 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..
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement