Easy Digital Downloads
  • Package
  • Function
  • Tree

Packages

  • EDD
    • Admin
      • Actions
      • Add-ons
      • Dashboard
      • Discounts
      • Downloads
      • Export
      • Notices
      • Pages
      • Payments
      • Reports
      • Settings
      • System
      • Upgrades
      • Upload
      • Welcome
    • Cart
    • Checkout
    • Classes
      • API
      • Fees
      • HTML
      • Roles
      • Session
    • Emails
    • Functions
      • AJAX
      • Compatibility
      • Errors
      • Formatting
      • Install
      • Login
      • Taxes
      • Templates
    • Gateways
    • Logging
    • Payments
    • Shortcodes
    • Widgets

Functions

  • edd_get_chosen_gateway
  • edd_get_default_gateway
  • edd_get_enabled_payment_gateways
  • edd_get_gateway_admin_label
  • edd_get_gateway_checkout_label
  • edd_get_payment_gateways
  • edd_get_paypal_page_style
  • edd_get_paypal_redirect
  • edd_is_gateway_active
  • edd_listen_for_paypal_ipn
  • edd_load_ajax_gateway
  • edd_manual_payment
  • edd_manual_remove_cc_form
  • edd_no_gateway_error
  • edd_process_paypal_ipn
  • edd_process_paypal_purchase
  • edd_process_paypal_refund
  • edd_process_paypal_web_accept
  • edd_record_gateway_error
  • edd_send_to_gateway
  • edd_show_gateways
  1 <?php
  2 /**
  3  * PayPal Standard Gateway
  4  *
  5  * @package     EDD
  6  * @subpackage  Gateways
  7  * @copyright   Copyright (c) 2013, Pippin Williamson
  8  * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
  9  * @since       1.0
 10  */
 11 
 12 /**
 13  * PayPal Remove CC Form
 14  *
 15  * PayPal Standard does not need a CC form, so remove it.
 16  *
 17  * @access private
 18  * @since 1.0
 19  */
 20 add_action( 'edd_paypal_cc_form', '__return_false' );
 21 
 22 /**
 23  * Process PayPal Purchase
 24  *
 25  * @since 1.0
 26  * @global $edd_options Array of all the EDD Options
 27  * @param array $purchase_data Purchase Data
 28  * @return void
 29  */
 30 function edd_process_paypal_purchase( $purchase_data ) {
 31     global $edd_options;
 32 
 33     // Check there is a gateway name
 34     if ( ! isset( $purchase_data['post_data']['edd-gateway'] ) )
 35         return;
 36 
 37     /*
 38     Purchase data comes in like this:
 39 
 40     $purchase_data = array(
 41         'downloads'     => array of download IDs,
 42         'tax'           => taxed amount on shopping cart
 43         'subtotal'      => total price before tax
 44         'price'         => total price of cart contents after taxes,
 45         'purchase_key'  =>  // Random key
 46         'user_email'    => $user_email,
 47         'date'          => date( 'Y-m-d H:i:s' ),
 48         'user_id'       => $user_id,
 49         'post_data'     => $_POST,
 50         'user_info'     => array of user's information and used discount code
 51         'cart_details'  => array of cart details,
 52      );
 53     */
 54 
 55     // Collect payment data
 56     $payment_data = array(
 57         'price'         => $purchase_data['price'],
 58         'date'          => $purchase_data['date'],
 59         'user_email'    => $purchase_data['user_email'],
 60         'purchase_key'  => $purchase_data['purchase_key'],
 61         'currency'      => $edd_options['currency'],
 62         'downloads'     => $purchase_data['downloads'],
 63         'user_info'     => $purchase_data['user_info'],
 64         'cart_details'  => $purchase_data['cart_details'],
 65         'status'        => 'pending'
 66      );
 67 
 68     // Record the pending payment
 69     $payment = edd_insert_payment( $payment_data );
 70 
 71     // Check payment
 72     if ( ! $payment ) {
 73         // Record the error
 74         edd_record_gateway_error( __( 'Payment Error', 'edd' ), sprintf( __( 'Payment creation failed before sending buyer to PayPal. Payment data: %s', 'edd' ), json_encode( $payment_data ) ), $payment );
 75         // Problems? send back
 76         edd_send_back_to_checkout( '?payment-mode=' . $purchase_data['post_data']['edd-gateway'] );
 77     } else {
 78         // Only send to PayPal if the pending payment is created successfully
 79         $listener_url = trailingslashit( home_url() ).'?edd-listener=IPN';
 80 
 81          // Get the success url
 82         $return_url = add_query_arg( 'payment-confirmation', 'paypal', get_permalink( $edd_options['success_page'] ) );
 83 
 84         // Get the complete cart cart_summary
 85         $summary = edd_get_purchase_summary( $purchase_data, false );
 86 
 87         // Get the PayPal redirect uri
 88         $paypal_redirect = trailingslashit( edd_get_paypal_redirect() ) . '?';
 89 
 90         // Setup PayPal arguments
 91         $paypal_args = array(
 92             'cmd'           => '_xclick',
 93             'amount'        => round( $purchase_data['price'] - $purchase_data['tax'], 2 ),
 94             'business'      => $edd_options['paypal_email'],
 95             'item_name'     => stripslashes_deep( html_entity_decode( wp_strip_all_tags( $summary ), ENT_COMPAT, 'UTF-8' ) ),
 96             'email'         => $purchase_data['user_email'],
 97             'no_shipping'   => '1',
 98             'shipping'      => '0',
 99             'no_note'       => '1',
100             'currency_code' => $edd_options['currency'],
101             'item_number'   => $purchase_data['purchase_key'],
102             'charset'       => get_bloginfo( 'charset' ),
103             'custom'        => $payment,
104             'rm'            => '2',
105             'return'        => $return_url,
106             'cancel_return' => edd_get_failed_transaction_uri(),
107             'notify_url'    => $listener_url,
108             'page_style'    => edd_get_paypal_page_style()
109         );
110 
111         if ( edd_use_taxes() )
112             $paypal_args['tax'] = $purchase_data['tax'];
113 
114         $paypal_args = apply_filters('edd_paypal_redirect_args', $paypal_args, $purchase_data );
115 
116         // Build query
117         $paypal_redirect .= http_build_query( $paypal_args );
118 
119         // Get rid of cart contents
120         edd_empty_cart();
121 
122         // Redirect to PayPal
123         wp_redirect( $paypal_redirect );
124         exit;
125     }
126 
127 }
128 add_action( 'edd_gateway_paypal', 'edd_process_paypal_purchase' );
129 
130 /**
131  * Listens for a PayPal IPN requests and then sends to the processing function
132  *
133  * @since 1.0
134  * @global $edd_options Array of all the EDD Options
135  * @return void
136  */
137 function edd_listen_for_paypal_ipn() {
138     global $edd_options;
139 
140     // Regular PayPal IPN
141     if ( isset( $_GET['edd-listener'] ) && $_GET['edd-listener'] == 'IPN' ) {
142         do_action( 'edd_verify_paypal_ipn' );
143     }
144 }
145 add_action( 'init', 'edd_listen_for_paypal_ipn' );
146 
147 /**
148  * Process PayPal IPN
149  *
150  * @since 1.0
151  * @global $edd_options Array of all the EDD Options
152  * @return void
153  */
154 function edd_process_paypal_ipn() {
155     global $edd_options;
156 
157     // Check the request method is POST
158     if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) {
159         return;
160     }
161 
162     // Set initial post data to false
163     $post_data = false;
164 
165     // Fallback just in case post_max_size is lower than needed
166     if ( ini_get( 'allow_url_fopen' ) ) {
167         $post_data = file_get_contents( 'php://input' );
168     } else {
169         // If allow_url_fopen is not enabled, then make sure that post_max_size is large enough
170         ini_set( 'post_max_size', '12M' );
171     }
172     // Start the encoded data collection with notification command
173     $encoded_data = 'cmd=_notify-validate';
174 
175     // Get current arg separator
176     $arg_separator = edd_get_php_arg_separator_output();
177 
178     // Verify there is a post_data
179     if ( $post_data || strlen( $post_data ) > 0 ) {
180         // Append the data
181         $encoded_data .= $arg_separator.$post_data;
182     } else {
183         // Check if POST is empty
184         if ( empty( $_POST ) ) {
185             // Nothing to do
186             return;
187         } else {
188             // Loop trough each POST
189             foreach ( $_POST as $key => $value ) {
190                 // Encode the value and append the data
191                 $encoded_data .= $arg_separator."$key=" . urlencode( $value );
192             }
193         }
194     }
195 
196     // Convert collected post data to an array
197     parse_str( $encoded_data, $encoded_data_array );
198 
199     // Get the PayPal redirect uri
200     $paypal_redirect = edd_get_paypal_redirect(true);
201 
202     $remote_post_vars      = array(
203         'method'           => 'POST',
204         'timeout'          => 45,
205         'redirection'      => 5,
206         'httpversion'      => '1.0',
207         'blocking'         => true,
208         'headers'          => array(
209             'host'         => 'www.paypal.com',
210             'connection'   => 'close',
211             'content-type' => 'application/x-www-form-urlencoded',
212             'post'         => '/cgi-bin/webscr HTTP/1.1',
213 
214         ),
215         'sslverify'        => false,
216         'body'             => $encoded_data_array
217     );
218 
219     // Get response
220     $api_response = wp_remote_post( edd_get_paypal_redirect(), $remote_post_vars );
221 
222     if ( is_wp_error( $api_response ) ) {
223         edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid IPN verification response. IPN data: ', 'edd' ), json_encode( $api_response ) ) );
224         return; // Something went wrong
225     }
226 
227     if ( $api_response['body'] !== 'VERIFIED' && !isset( $edd_options['disable_paypal_verification'] ) ) {
228         edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid IPN verification response. IPN data: ', 'edd' ), json_encode( $api_response ) ) );
229         return; // Response not okay
230     }
231 
232     // Check if $post_data_array has been populated
233     if ( ! is_array( $encoded_data_array ) && !empty( $encoded_data_array ) )
234         return;
235 
236     if ( has_action( 'edd_paypal_' . $encoded_data_array['txn_type'] ) ) {
237         // Allow PayPal IPN types to be processed separately
238         do_action( 'edd_paypal_' . $encoded_data_array['txn_type'], $encoded_data_array );
239     } else {
240         // Fallback to web accept just in case the txn_type isn't present
241         do_action( 'edd_paypal_web_accept', $encoded_data_array );
242     }
243 }
244 add_action( 'edd_verify_paypal_ipn', 'edd_process_paypal_ipn' );
245 
246 /**
247  * Process web accept (one time) payment IPNs
248  *
249  * @since 1.3.4
250  * @global $edd_options Array of all the EDD Options
251  * @param array $data IPN Data
252  * @return void
253  */
254 function edd_process_paypal_web_accept( $data ) {
255     global $edd_options;
256 
257     if ( $data['txn_type'] != 'web_accept' )
258         return;
259 
260     // Collect payment details
261     $payment_id     = $data['custom'];
262     $purchase_key   = $data['item_number'];
263     $paypal_amount  = $data['mc_gross'];
264     $payment_status = strtolower( $data['payment_status'] );
265     $currency_code  = strtolower( $data['mc_currency'] );
266 
267     // Retrieve the meta info for this payment
268     $payment_amount = edd_format_amount( edd_get_payment_amount( $payment_id ) );
269 
270     if( get_post_status( $payment_id ) == 'complete' )
271         return; // Only complete payments once
272 
273     if ( edd_get_payment_gateway( $payment_id ) != 'paypal' )
274         return; // this isn't a PayPal standard IPN
275 
276     // Verify details
277     if ( $currency_code != strtolower( $edd_options['currency'] ) ) {
278         // The currency code is invalid
279 
280         edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid currency in IPN response. IPN data: ', 'edd' ), json_encode( $data ) ), $payment_id );
281         edd_update_payment_status( $payment_id, 'failed' );
282         return;
283     }
284 
285     if ( $payment_status == 'refunded' ) {
286         // Process a refund
287         edd_process_paypal_refund( $data );
288     } else {
289         if ( number_format( (float)$paypal_amount, 2) != $payment_amount ) {
290             // The prices don't match
291             edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid payment amount in IPN response. IPN data: ', 'edd' ), json_encode( $data ) ), $payment_id );
292            //return;
293         }
294         if ( $purchase_key != edd_get_payment_key( $payment_id ) ) {
295             // Purchase keys don't match
296             edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid purchase key in IPN response. IPN data: ', 'edd' ), json_encode( $data ) ), $payment_id );
297             edd_update_payment_status( $payment_id, 'failed' );
298             return;
299         }
300 
301         if ( $payment_status == 'completed' || edd_is_test_mode() ) {
302             edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Transaction ID: %s', 'edd' ) , $data['txn_id'] ) );
303             edd_update_payment_status( $payment_id, 'publish' );
304         }
305     }
306 }
307 add_action( 'edd_paypal_web_accept', 'edd_process_paypal_web_accept' );
308 
309 /**
310  * Process PayPal IPN Refunds
311  *
312  * @since 1.3.4
313  * @global $edd_options Array of all the EDD Options
314  * @param array $data IPN Data
315  * @return void
316  */
317 function edd_process_paypal_refund( $data ) {
318     global $edd_options;
319 
320     // Collect payment details
321     $payment_id = intval( $data['custom'] );
322 
323     edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Payment #%s Refunded', 'edd' ) , $data['parent_txn_id'] ) );
324     edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Refund Transaction ID: %s', 'edd' ) , $data['txn_id'] ) );
325     edd_update_payment_status( $payment_id, 'refunded' );
326 }
327 
328 /**
329  * Get PayPal Redirect
330  *
331  * @since 1.0.8.2
332  * @global $edd_options Array of all the EDD Options
333  * @param bool $ssl_check Is SSL?
334  * @return string
335  */
336 function edd_get_paypal_redirect( $ssl_check = false ) {
337     global $edd_options;
338 
339     if ( is_ssl() || ! $ssl_check ) {
340         $protocal = 'https://';
341     } else {
342         $protocal = 'http://';
343     }
344 
345     // Check the current payment mode
346     if ( edd_is_test_mode() ) {
347         // Test mode
348         $paypal_uri = $protocal . 'www.sandbox.paypal.com/cgi-bin/webscr';
349     } else {
350         // Live mode
351         $paypal_uri = $protocal . 'www.paypal.com/cgi-bin/webscr';
352     }
353 
354     return $paypal_uri;
355 }
356 
357 /**
358  * Set the Page Style for PayPal Purchase page
359  *
360  * @since 1.4.1
361  * @global $edd_options Array of all the EDD Options
362  * @return string
363  */
364 function edd_get_paypal_page_style() {
365     global $edd_options;
366 
367     $page_style = 'PayPal';
368 
369     if ( isset( $edd_options['paypal_page_style'] ) )
370         $page_style = trim( $edd_options['paypal_page_style'] );
371 
372     return apply_filters( 'edd_paypal_page_style', $page_style );
373 }
Easy Digital Downloads API documentation generated by ApiGen 2.8.0