/** * When a PayPal IPN messaged is received for a subscription transaction, * check the transaction details and * * @since 1.0 */ public static function process_paypal_ipn_request($transaction_details) { if (!in_array($transaction_details['txn_type'], array('subscr_signup', 'subscr_payment', 'subscr_cancel', 'subscr_eot', 'subscr_failed', 'subscr_modify'))) { return; } if (empty($transaction_details['custom']) || empty($transaction_details['invoice'])) { return; } // Get the $order_id & $order_key with backward compatibility extract(self::get_order_id_and_key($transaction_details)); $transaction_details['txn_type'] = strtolower($transaction_details['txn_type']); if (self::$debug) { self::$log->add('paypal', 'Subscription Transaction Type: ' . $transaction_details['txn_type']); } if (self::$debug && 'subscr_modify' == $transaction_details['txn_type']) { self::$log->add('paypal', 'Subscription subscr_modify details: ' . print_r($transaction_details, true)); } $order = new WC_Order($order_id); if ($order->order_key !== $order_key) { if (self::$debug) { self::$log->add('paypal', 'Subscription IPN Error: Order Key does not match invoice.'); } return; } switch ($transaction_details['txn_type']) { case 'subscr_signup': // Store PayPal Details update_post_meta($order_id, 'Payer PayPal address', $transaction_details['payer_email']); update_post_meta($order_id, 'Payer PayPal first name', $transaction_details['first_name']); update_post_meta($order_id, 'Payer PayPal last name', $transaction_details['last_name']); update_post_meta($order_id, 'PayPal Subscriber ID', $transaction_details['subscr_id']); // Payment completed if (!in_array($order->status, array('completed', 'processing'))) { $order->add_order_note(__('IPN subscription sign up completed.', WC_Subscriptions::$text_domain)); if (self::$debug) { self::$log->add('paypal', 'IPN subscription sign up completed for order ' . $order_id); } $order->payment_complete(); WC_Subscriptions_Manager::activate_subscriptions_for_order($order); } break; case 'subscr_payment': if ('completed' == strtolower($transaction_details['payment_status'])) { // Store PayPal Details update_post_meta($order_id, 'Transaction ID', $transaction_details['txn_id']); update_post_meta($order_id, 'Payer first name', $transaction_details['first_name']); update_post_meta($order_id, 'Payer last name', $transaction_details['last_name']); update_post_meta($order_id, 'Payment type', $transaction_details['payment_type']); // Subscription Payment completed $order->add_order_note(__('IPN subscription payment completed.', WC_Subscriptions::$text_domain)); if (self::$debug) { self::$log->add('paypal', 'IPN subscription payment completed for order ' . $order_id); } WC_Subscriptions_Manager::process_subscription_payments_on_order($order); } elseif ('failed' == strtolower($transaction_details['payment_status'])) { // Subscription Payment completed $order->add_order_note(__('IPN subscription payment failed.', WC_Subscriptions::$text_domain)); if (self::$debug) { self::$log->add('paypal', 'IPN subscription payment failed for order ' . $order_id); } WC_Subscriptions_Manager::process_subscription_payment_failure_on_order($order); } else { if (self::$debug) { self::$log->add('paypal', 'IPN subscription payment notification received for order ' . $order_id . ' with status ' . $transaction_details['payment_status']); } } break; case 'subscr_cancel': if (self::$debug) { self::$log->add('paypal', 'IPN subscription cancelled for order ' . $order_id); } // Subscription Payment completed $order->add_order_note(__('IPN subscription cancelled for order.', WC_Subscriptions::$text_domain)); WC_Subscriptions_Manager::cancel_subscriptions_for_order($order); break; case 'subscr_eot': // Subscription ended if (self::$debug) { self::$log->add('paypal', 'IPN subscription expired for order ' . $order_id); } // Subscription Payment completed $order->add_order_note(__('IPN subscription expired for order.', WC_Subscriptions::$text_domain)); WC_Subscriptions_Manager::expire_subscriptions_for_order($order); break; case 'subscr_failed': // Subscription sign up failed if (self::$debug) { self::$log->add('paypal', 'IPN subscription sign up failure for order ' . $order_id); } // Subscription Payment completed $order->add_order_note(__('IPN subscription sign up failure.', WC_Subscriptions::$text_domain)); WC_Subscriptions_Manager::failed_subscription_sign_ups_for_order($order); break; } // Prevent default IPN handling for subscription txn_types exit; }
/** * When a PayPal IPN messaged is received for a subscription transaction, * check the transaction details and * * @since 1.0 */ public static function process_paypal_ipn_request($transaction_details) { if (!in_array($transaction_details['txn_type'], array('subscr_signup', 'subscr_payment', 'subscr_cancel', 'subscr_eot', 'subscr_failed', 'subscr_modify'))) { return; } if (empty($transaction_details['custom']) || empty($transaction_details['invoice'])) { return; } // Get the $order_id & $order_key with backward compatibility extract(self::get_order_id_and_key($transaction_details)); $transaction_details['txn_type'] = strtolower($transaction_details['txn_type']); if (self::$debug) { self::$log->add('paypal', 'Subscription Transaction Type: ' . $transaction_details['txn_type']); } if (self::$debug) { self::$log->add('paypal', 'Subscription transaction details: ' . print_r($transaction_details, true)); } $order = new WC_Order($order_id); // We have an invalid $order_id, probably because invoice_prefix has changed since the subscription was first created, so get the if (!isset($order->id)) { $order_id = function_exists('woocommerce_get_order_id_by_order_key') ? woocommerce_get_order_id_by_order_key($order_key) : $wpdb->get_var("SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_key = '_order_key' AND meta_value = '{$order_key}'"); $order = new WC_Order($order_id); } if ($order->order_key !== $order_key) { if (self::$debug) { self::$log->add('paypal', 'Subscription IPN Error: Order Key does not match invoice.'); } return; } switch ($transaction_details['txn_type']) { case 'subscr_signup': // Store PayPal Details update_post_meta($order_id, 'Payer PayPal address', $transaction_details['payer_email']); update_post_meta($order_id, 'Payer PayPal first name', $transaction_details['first_name']); update_post_meta($order_id, 'Payer PayPal last name', $transaction_details['last_name']); update_post_meta($order_id, 'PayPal Subscriber ID', $transaction_details['subscr_id']); // Payment completed $order->add_order_note(__('IPN subscription sign up completed.', WC_Subscriptions::$text_domain)); if (self::$debug) { self::$log->add('paypal', 'IPN subscription sign up completed for order ' . $order_id); } // When there is a free trial & no initial payment amount, we need to mark the order as paid and activate the subscription if (0 == WC_Subscriptions_Order::get_total_initial_payment($order) && WC_Subscriptions_Order::get_subscription_trial_length($order) > 0) { $order->payment_complete(); WC_Subscriptions_Manager::activate_subscriptions_for_order($order); } break; case 'subscr_payment': if ('completed' == strtolower($transaction_details['payment_status'])) { // Store PayPal Details update_post_meta($order_id, 'PayPal Transaction ID', $transaction_details['txn_id']); update_post_meta($order_id, 'Payer PayPal first name', $transaction_details['first_name']); update_post_meta($order_id, 'Payer PayPal last name', $transaction_details['last_name']); update_post_meta($order_id, 'PayPal Payment type', $transaction_details['payment_type']); // Subscription Payment completed $order->add_order_note(__('IPN subscription payment completed.', WC_Subscriptions::$text_domain)); if (self::$debug) { self::$log->add('paypal', 'IPN subscription payment completed for order ' . $order_id); } $subscriptions_in_order = WC_Subscriptions_Order::get_recurring_items($order); $subscription_item = array_pop($subscriptions_in_order); $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order->id, $subscription_item['id']); $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key, $order->customer_user); // First payment on order, process payment & activate subscription if (empty($subscription['completed_payments'])) { $order->payment_complete(); WC_Subscriptions_Manager::activate_subscriptions_for_order($order); } else { WC_Subscriptions_Manager::process_subscription_payments_on_order($order); } } elseif ('failed' == strtolower($transaction_details['payment_status'])) { // Subscription Payment completed $order->add_order_note(__('IPN subscription payment failed.', WC_Subscriptions::$text_domain)); if (self::$debug) { self::$log->add('paypal', 'IPN subscription payment failed for order ' . $order_id); } WC_Subscriptions_Manager::process_subscription_payment_failure_on_order($order); } else { if (self::$debug) { self::$log->add('paypal', 'IPN subscription payment notification received for order ' . $order_id . ' with status ' . $transaction_details['payment_status']); } } break; case 'subscr_cancel': if (self::$debug) { self::$log->add('paypal', 'IPN subscription cancelled for order ' . $order_id); } // Subscription Payment completed $order->add_order_note(__('IPN subscription cancelled for order.', WC_Subscriptions::$text_domain)); WC_Subscriptions_Manager::cancel_subscriptions_for_order($order); break; case 'subscr_eot': // Subscription ended, either due to failed payments or expiration // PayPal fires the 'subscr_eot' notice immediately if a subscription is only for one billing period, so ignore the request when we only have one billing period if (1 != WC_Subscriptions_Order::get_subscription_length($order)) { if (self::$debug) { self::$log->add('paypal', 'IPN subscription end-of-term for order ' . $order_id); } // Record subscription ended $order->add_order_note(__('IPN subscription end-of-term for order.', WC_Subscriptions::$text_domain)); // Ended due to failed payments so cancel the subscription if (time() < strtotime(WC_Subscriptions_Manager::get_subscription_expiration_date(WC_Subscriptions_Manager::get_subscription_key($order->id), $order->customer_user))) { WC_Subscriptions_Manager::cancel_subscriptions_for_order($order); } else { WC_Subscriptions_Manager::expire_subscriptions_for_order($order); } } break; case 'subscr_failed': // Subscription sign up failed if (self::$debug) { self::$log->add('paypal', 'IPN subscription sign up failure for order ' . $order_id); } // Subscription Payment completed $order->add_order_note(__('IPN subscription sign up failure.', WC_Subscriptions::$text_domain)); WC_Subscriptions_Manager::failed_subscription_sign_ups_for_order($order); break; } // Prevent default IPN handling for subscription txn_types exit; }