/** * Process PayPal IPN * * @since 2.1 */ public function process_webhooks() { if (!isset($_GET['listener']) || strtoupper($_GET['listener']) != 'IPN') { return; } global $rcp_options; nocache_headers(); if (!class_exists('IpnListener')) { // instantiate the IpnListener class include RCP_PLUGIN_DIR . 'includes/gateways/paypal/paypal-ipnlistener.php'; } $listener = new IpnListener(); $verified = false; if ($this->test_mode) { $listener->use_sandbox = true; } /* if( isset( $rcp_options['ssl'] ) ) { $listener->use_ssl = true; } else { $listener->use_ssl = false; } */ //To post using the fsockopen() function rather than cURL, use: if (isset($rcp_options['disable_curl'])) { $listener->use_curl = false; } try { $listener->requirePostMethod(); $verified = $listener->processIpn(); } catch (Exception $e) { status_header(402); //die( 'IPN exception: ' . $e->getMessage() ); } /* The processIpn() method returned true if the IPN was "VERIFIED" and false if it was "INVALID". */ if ($verified || isset($_POST['verification_override']) || ($this->test_mode || isset($rcp_options['disable_ipn_verify']))) { status_header(200); $user_id = 0; $posted = apply_filters('rcp_ipn_post', $_POST); // allow $_POST to be modified if (!empty($posted['custom']) && is_numeric($posted['custom'])) { $user_id = absint($posted['custom']); } else { if (!empty($posted['subscr_id'])) { $user_id = rcp_get_member_id_from_profile_id($posted['subscr_id']); } else { if (!empty($posted['payer_email'])) { $user = get_user_by('email', $posted['payer_email']); $user_id = $user ? $user->ID : false; } } } $member = new RCP_Member($user_id); if (!$member || !$member->get_subscription_id()) { die('no member found'); } if (!rcp_get_subscription_details($member->get_subscription_id())) { die('no subscription level found'); } $subscription_name = $posted['item_name']; $subscription_key = $posted['item_number']; $amount = number_format((double) $posted['mc_gross'], 2); $amount2 = number_format((double) $posted['mc_amount3'], 2); $payment_status = $posted['payment_status']; $currency_code = $posted['mc_currency']; $subscription_price = number_format((double) rcp_get_subscription_price($member->get_subscription_id()), 2); // setup the payment info in an array for storage $payment_data = array('date' => date('Y-m-d g:i:s', strtotime($posted['payment_date'], current_time('timestamp'))), 'subscription' => $posted['item_name'], 'payment_type' => $posted['txn_type'], 'subscription_key' => $subscription_key, 'amount' => $amount, 'user_id' => $user_id, 'transaction_id' => $posted['txn_id']); do_action('rcp_valid_ipn', $payment_data, $user_id, $posted); if ($posted['txn_type'] == 'web_accept' || $posted['txn_type'] == 'subscr_payment') { // only check for an existing payment if this is a payment IPD request if (rcp_check_for_existing_payment($posted['txn_type'], $posted['payment_date'], $subscription_key)) { $log_data = array('post_title' => __('Duplicate Payment', 'rcp'), 'post_content' => __('A duplicate payment was detected. The new payment was still recorded, so you may want to check into both payments.', 'rcp'), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); die('duplicate IPN detected'); } if (strtolower($currency_code) != strtolower($rcp_options['currency'])) { // the currency code is invalid $log_data = array('post_title' => __('Invalid Currency Code', 'rcp'), 'post_content' => sprintf(__('The currency code in an IPN request did not match the site currency code. Payment data: %s', 'rcp'), json_encode($payment_data)), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); die('invalid currency code'); } } if (isset($rcp_options['email_ipn_reports'])) { wp_mail(get_bloginfo('admin_email'), __('IPN report', 'rcp'), $listener->getTextReport()); } /* now process the kind of subscription/payment */ $rcp_payments = new RCP_Payments(); // Subscriptions switch ($posted['txn_type']) { case "subscr_signup": // when a new user signs up // store the recurring payment ID update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); $member->set_payment_profile_id($posted['subscr_id']); do_action('rcp_ipn_subscr_signup', $user_id); die('successful subscr_signup'); break; case "subscr_payment": // when a user makes a recurring payment update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); $member->set_payment_profile_id($posted['subscr_id']); $member->renew(true); // record this payment in the database $rcp_payments->insert($payment_data); do_action('rcp_ipn_subscr_payment', $user_id); die('successful subscr_payment'); break; case "subscr_cancel": // user is marked as cancelled but retains access until end of term $member->set_status('cancelled'); // set the use to no longer be recurring delete_user_meta($user_id, 'rcp_paypal_subscriber'); do_action('rcp_ipn_subscr_cancel', $user_id); die('successful subscr_cancel'); break; case "subscr_failed": do_action('rcp_ipn_subscr_failed'); die('successful subscr_failed'); break; case "subscr_eot": // user's subscription has reached the end of its term if ('cancelled' !== $member->get_status($user_id)) { $member->set_status('expired'); } do_action('rcp_ipn_subscr_eot', $user_id); die('successful subscr_eot'); break; case "web_accept": switch (strtolower($payment_status)) { case 'completed': // set this user to active $member->renew(); $rcp_payments->insert($payment_data); break; case 'denied': case 'expired': case 'failed': case 'voided': $member->set_status('cancelled'); break; } die('successful web_accept'); break; case "cart": case "express_checkout": default: break; } } else { if (isset($rcp_options['email_ipn_reports'])) { // an invalid IPN attempt was made. Send an email to the admin account to investigate wp_mail(get_bloginfo('admin_email'), __('Invalid IPN', 'rcp'), $listener->getTextReport()); } status_header(400); die('invalid IPN'); } }
function rcp_check_ipn() { global $rcp_options; if (!class_exists('IpnListener')) { // instantiate the IpnListener class include RCP_PLUGIN_DIR . 'includes/gateways/paypal/ipnlistener.php'; } $listener = new IpnListener(); if (isset($rcp_options['sandbox'])) { $listener->use_sandbox = true; } if (isset($rcp_options['ssl'])) { $listener->use_ssl = true; } else { $listener->use_ssl = false; } //To post using the fsockopen() function rather than cURL, use: if (isset($rcp_options['disable_curl'])) { $listener->use_curl = false; } try { $listener->requirePostMethod(); $verified = $listener->processIpn(); } catch (Exception $e) { //exit(0); } /* The processIpn() method returned true if the IPN was "VERIFIED" and false if it was "INVALID". */ if ($verified || isset($_POST['verification_override']) || (isset($rcp_options['sandbox']) || isset($rcp_options['disable_ipn_verify']))) { $posted = apply_filters('rcp_ipn_post', $_POST); // allow $_POST to be modified $user_id = $posted['custom']; $subscription_name = $posted['item_name']; $subscription_key = $posted['item_number']; $amount = number_format((double) $posted['mc_gross'], 2); $amount2 = number_format((double) $posted['mc_amount3'], 2); $payment_status = $posted['payment_status']; $currency_code = $posted['mc_currency']; $subscription_id = rcp_get_subscription_id($user_id); $subscription_price = number_format((double) rcp_get_subscription_price(rcp_get_subscription_id($user_id)), 2); $user_data = get_userdata($user_id); if (!$user_data || !$subscription_id) { return; } if (!rcp_get_subscription_details($subscription_id)) { return; } // setup the payment info in an array for storage $payment_data = array('date' => date('Y-m-d g:i:s', strtotime($posted['payment_date'])), 'subscription' => $posted['item_name'], 'payment_type' => $posted['txn_type'], 'subscription_key' => $subscription_key, 'amount' => $amount, 'user_id' => $user_id, 'transaction_id' => $posted['txn_id']); do_action('rcp_valid_ipn', $payment_data, $user_id, $posted); if ($posted['txn_type'] == 'web_accept' || $posted['txn_type'] == 'subscr_payment') { // only check for an existing payment if this is a payment IPD request if (rcp_check_for_existing_payment($posted['txn_type'], $posted['payment_date'], $subscription_key)) { $log_data = array('post_title' => __('Duplicate Payment', 'rcp'), 'post_content' => __('A duplicate payment was detected. The new payment was still recorded, so you may want to check into both payments.', 'rcp'), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); return; // this IPN request has already been processed } /* do some quick checks to make sure all necessary data validates */ if ($amount < $subscription_price && $amount2 < $subscription_price) { /* // the subscription price doesn't match, so lets check to see if it matches with a discount code if( ! rcp_check_paypal_return_price_after_discount( $subscription_price, $amount, $amount2, $user_id ) ) { $log_data = array( 'post_title' => __( 'Price Mismatch', 'rcp' ), 'post_content' => sprintf( __( 'The price in an IPN request did not match the subscription price. Payment data: %s', 'rcp' ), json_encode( $payment_data ) ), 'post_parent' => 0, 'log_type' => 'gateway_error' ); $log_meta = array( 'user_subscription' => $posted['item_name'], 'user_id' => $user_id ); $log_entry = WP_Logging::insert_log( $log_data, $log_meta ); //return; } */ } if (strtolower($currency_code) != strtolower($rcp_options['currency'])) { // the currency code is invalid $log_data = array('post_title' => __('Invalid Currency Code', 'rcp'), 'post_content' => sprintf(__('The currency code in an IPN request did not match the site currency code. Payment data: %s', 'rcp'), json_encode($payment_data)), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); return; } } if (isset($rcp_options['email_ipn_reports'])) { wp_mail(get_bloginfo('admin_email'), __('IPN report', 'rcp'), $listener->getTextReport()); } if (rcp_get_subscription_key($user_id) != $subscription_key) { // the subscription key is invalid $log_data = array('post_title' => __('Subscription Key Mismatch', 'rcp'), 'post_content' => sprintf(__('The subscription key in an IPN request did not match the subscription key recorded for the user. Payment data: %s', 'rcp'), json_encode($payment_data)), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); return; } /* now process the kind of subscription/payment */ $rcp_payments = new RCP_Payments(); // Subscriptions switch ($posted['txn_type']) { case "subscr_signup": // when a new user signs up // store the recurring payment ID update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); // set the user's status to active rcp_set_status($user_id, 'active'); if (!isset($rcp_options['disable_new_user_notices'])) { wp_new_user_notification($user_id); } // send welcome email rcp_email_subscription_status($user_id, 'active'); update_user_meta($user_id, 'rcp_recurring', 'yes'); do_action('rcp_ipn_subscr_signup', $user_id); break; case "subscr_payment": // when a user makes a recurring payment // record this payment in the database $rcp_payments->insert($payment_data); $subscription = rcp_get_subscription_details(rcp_get_subscription_id($user_id)); // update the user's expiration to correspond with the new payment $member_new_expiration = date('Y-m-d H:i:s', strtotime('+' . $subscription->duration . ' ' . $subscription->duration_unit . ' 23:59:59')); rcp_set_expiration_date($user_id, $member_new_expiration); update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); // make sure the user's status is active rcp_set_status($user_id, 'active'); update_user_meta($user_id, 'rcp_recurring', 'yes'); delete_user_meta($user_id, '_rcp_expired_email_sent'); do_action('rcp_ipn_subscr_payment', $user_id); break; case "subscr_cancel": // user is marked as cancelled but retains access until end of term rcp_set_status($user_id, 'cancelled'); // set the use to no longer be recurring delete_user_meta($user_id, 'rcp_recurring'); delete_user_meta($user_id, 'rcp_paypal_subscriber'); // send sub cancelled email rcp_email_subscription_status($user_id, 'cancelled'); do_action('rcp_ipn_subscr_cancel', $user_id); break; case "subscr_failed": do_action('rcp_ipn_subscr_failed'); break; case "subscr_eot": // user's subscription has reach the end of its term // set the use to no longer be recurring delete_user_meta($user_id, 'rcp_recurring'); if ('cancelled' !== rcp_get_status($user_id)) { rcp_set_status($user_id, 'expired'); // send expired email rcp_email_subscription_status($user_id, 'expired'); } do_action('rcp_ipn_subscr_eot', $user_id); break; case "cart": return; // get out of here // get out of here case "express_checkout": return; // get out of here // get out of here case "web_accept": switch (strtolower($payment_status)) { case 'completed': if (isset($_POST['verification_override'])) { // this is a method for providing a new expiration if it doesn't exist $subscription = rcp_get_subscription_details_by_name($payment_data['subscription']); // update the user's expiration to correspond with the new payment $member_new_expiration = date('Y-m-d H:i:s', strtotime('+' . $subscription->duration . ' ' . $subscription->duration_unit . ' 23:59:59')); rcp_set_expiration_date($user_id, $member_new_expiration); } // set this user to active rcp_set_status($user_id, 'active'); $rcp_payments->insert($payment_data); rcp_email_subscription_status($user_id, 'active'); if (!isset($rcp_options['disable_new_user_notices'])) { // send welcome email here wp_new_user_notification($user_id); } delete_user_meta($user_id, '_rcp_expired_email_sent'); break; case 'denied': case 'expired': case 'failed': case 'voided': rcp_set_status($user_id, 'cancelled'); // send cancelled email here break; } break; default: break; } } else { if (isset($rcp_options['email_ipn_reports'])) { // an invalid IPN attempt was made. Send an email to the admin account to investigate wp_mail(get_bloginfo('admin_email'), __('Invalid IPN', 'rcp'), $listener->getTextReport()); } } }
/** * Insert a payment into the database * * @deprecated 1.5 * @access private * @param $payment_data ARRAY The data to store * @return INT the ID of the new payment, or false if insertion fails */ function rcp_insert_payment($payment_data = array()) { global $wpdb, $rcp_payments_db_name; $amount = $payment_data['amount']; if ($payment_data['amount'] == '') { $amount = $payment_data['amount2']; } if (rcp_check_for_existing_payment($payment_data['payment_type'], $payment_data['date'], $payment_data['subscription_key'])) { return; } $wpdb->insert($rcp_payments_db_name, array('subscription' => $payment_data['subscription'], 'date' => $payment_data['date'], 'amount' => $amount, 'user_id' => $payment_data['user_id'], 'payment_type' => $payment_data['payment_type'], 'subscription_key' => $payment_data['subscription_key']), array('%s', '%s', '%s', '%d', '%s', '%s')); // if insert was succesful, return the payment ID if ($wpdb->insert_id) { // clear the payment caches delete_transient('rcp_payments'); delete_transient('rcp_earnings'); delete_transient('rcp_payments_count'); do_action('rcp_insert_payment', $wpdb->insert_id, $payment_data, $amount); return $wpdb->insert_id; } // return false if payment wasn't recorded return false; }
public function process_webhooks() { if (!isset($_GET['listener']) || strtolower($_GET['listener']) != 'stripe') { return; } // Ensure listener URL is not cached by W3TC define('DONOTCACHEPAGE', true); \Stripe\Stripe::setApiKey($this->secret_key); // retrieve the request's body and parse it as JSON $body = @file_get_contents('php://input'); $event_json_id = json_decode($body); // for extra security, retrieve from the Stripe API if (isset($event_json_id->id)) { $rcp_payments = new RCP_Payments(); $event_id = $event_json_id->id; try { $event = \Stripe\Event::retrieve($event_id); $invoice = $event->data->object; if (empty($invoice->customer)) { die('no customer attached'); } // retrieve the customer who made this payment (only for subscriptions) $user = rcp_get_member_id_from_profile_id($invoice->customer); if (empty($user)) { // Grab the customer ID from the old meta keys global $wpdb; $user = $wpdb->get_var($wpdb->prepare("SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = '_rcp_stripe_user_id' AND meta_value = %s LIMIT 1", $invoice->customer)); } if (empty($user)) { die('no user ID found'); } $member = new RCP_Member($user); // check to confirm this is a stripe subscriber if ($member) { // successful payment if ($event->type == 'charge.succeeded') { if (!$member->get_subscription_id()) { die('no subscription ID for member'); } $payment_data = array('date' => date('Y-m-d g:i:s', $event->created), 'subscription' => $member->get_subscription_name(), 'payment_type' => 'Credit Card', 'subscription_key' => $member->get_subscription_key(), 'amount' => $invoice->amount / 100, 'user_id' => $member->ID, 'transaction_id' => $invoice->id); if (!rcp_check_for_existing_payment($payment_data['payment_type'], $payment_data['date'], $payment_data['subscription_key'])) { // record this payment if it hasn't been recorded yet $rcp_payments->insert($payment_data); $member->renew($member->is_recurring()); do_action('rcp_stripe_charge_succeeded', $user, $payment_data); die('rcp_stripe_charge_succeeded action fired successfully'); } else { die('duplicate payment found'); } } // failed payment if ($event->type == 'charge.failed') { do_action('rcp_stripe_charge_failed', $invoice); die('rcp_stripe_charge_failed action fired successfully'); } // Cancelled / failed subscription if ($event->type == 'customer.subscription.deleted') { $member->set_status('cancelled'); die('member cancelled successfully'); } do_action('rcp_stripe_' . $event->type, $invoice); } } catch (Exception $e) { // something failed die('PHP exception: ' . $e->getMessage()); } die('1'); } die('no event ID found'); }