/** * Helper method to cancel a subscription at Stripe and also clear up any upaid invoices. * * @since 1.8 */ function cancelSubscriptionAtGateway($subscription) { //need a valid sub if (empty($subscription->id)) { return false; } //make sure we get the customer for this subscription $order = new MemberOrder(); $order->getLastMemberOrderBySubscriptionTransactionID($subscription->id); //no order? if (empty($order)) { //lets cancel anyway, but this is suspicious $r = $subscription->cancel(); return true; } //okay have an order, so get customer so we can cancel invoices too $this->getCustomer($order); //get open invoices $invoices = $this->customer->invoices(); $invoices = $invoices->all(); //found it, cancel it try { //find any open invoices for this subscription and forgive them if (!empty($invoices)) { foreach ($invoices->data as $invoice) { if (!$invoice->closed && $invoice->subscription == $subscription->id) { $invoice->closed = true; $invoice->save(); } } } //cancel $r = $subscription->cancel(); return true; } catch (Exception $e) { return false; } }
$pmproemail->sendBillingFailureEmail($user, $morder); // Email admin so they are aware of the failure $pmproemail = new PMProEmail(); $pmproemail->sendBillingFailureAdminEmail(get_bloginfo("admin_email"), $morder); echo "Sent email to the member and site admin. Thanks."; exit; } //subscription cancelled (they used one l canceled) if ($webhookNotification->kind == "subscription_canceled") { //need a subscription id if (empty($webhookNotification->subscription->id)) { die("No subscription ID."); } //figure out which order to attach to $old_order = new MemberOrder(); $old_order->getLastMemberOrderBySubscriptionTransactionID($webhookNotification->subscription->id); if (empty($old_order)) { die("Couldn't find old order for failed payment with subscription id=" . $webhookNotification->subscription->id); } //generate billing failure email do_action("pmpro_subscription_cancelled", $old_order); $transaction = $webhookNotification->transactions[0]; //prep this order for the failure emails $morder = new MemberOrder(); $morder->user_id = $user_id; $morder->billing->name = trim($transaction->billing_details->first_name . " " . $transaction->billing_details->first_name); $morder->billing->street = $transaction->billing_details->street_address; $morder->billing->city = $transaction->billing_details->locality; $morder->billing->state = $transaction->billing_details->region; $morder->billing->zip = $transaction->billing_details->postal_code; $morder->billing->country = $transaction->billing_details->country_code_alpha2;
//send an email to the member $myemail = new PMProEmail(); $myemail->sendCancelEmail($user); //send an email to the admin $myemail = new PMProEmail(); $myemail->sendCancelAdminEmail($user, $last_subscr_order->membership_id); } } pmpro_ipnExit(); } } //Subscription Cancelled (PayPal Standard) if ($txn_type == "subscr_cancel") { //find last order $last_subscr_order = new MemberOrder(); if ($last_subscr_order->getLastMemberOrderBySubscriptionTransactionID($subscr_id) == false) { ipnlog("ERROR: Couldn't find this order to cancel (subscription_transaction_id=" . $subscr_id . ")."); pmpro_ipnExit(); } else { //found order, let's cancel the membership $user = get_userdata($last_subscr_order->user_id); if (empty($user) || empty($user->ID)) { ipnlog("ERROR: Could not cancel membership. No user attached to order #" . $last_subscr_order->id . " with subscription transaction id = " . $subscr_id . "."); } else { /* We want to make sure this is a cancel originating from PayPal and not one already handled by PMPro. For example, if a user cancels on WP/PMPro side, we've already cancelled the membership. Also, if a user is changing levels, we don't want to cancel their new membership, just the old subscription at PayPal. So we check 2 things and don't cancel if: (1) This order already has "cancelled" status.
//update membership if (pmpro_insChangeMembershipLevel($txn_id, $morder)) { inslog("Checkout processed (" . $morder->code . ") success!"); } else { inslog("ERROR: Couldn't change level for order (" . $morder->code . ")."); } } else { pmpro_insSaveOrder($txn_id, $last_subscr_order); } pmpro_twocheckoutExit(); } // Recurring Payment Failed (recurring installment failed and recurring is true) if ($message_type == 'RECURRING_INSTALLMENT_FAILED' && $recurring) { //is this a first payment? $last_subscr_order = new MemberOrder(); $last_subscr_order->getLastMemberOrderBySubscriptionTransactionID($txn_id); pmpro_insFailedPayment($last_subscr_order); pmpro_twocheckoutExit(); } /* // Recurring Payment Stopped (recurring stopped and recurring is true) if( $message_type == 'RECURRING_STOPPED' && $recurring ) { //initial payment, get the order $morder = new MemberOrder( $product_id ); $morder->getMembershipLevel(); $morder->getUser(); // stop membership if ( pmpro_insRecurringStopped( $morder ) ) { inslog( "Recurring stopped for order (" . $morder->code . ")!" ); }
//$pmpro_stripe_event = $post_event; //for testing you may want to assume that the passed in event is legit } } global $wpdb; //real event? if (!empty($pmpro_stripe_event->id)) { //check what kind of event it is if ($pmpro_stripe_event->type == "invoice.payment_succeeded") { if ($pmpro_stripe_event->data->object->amount_due > 0) { //do we have this order yet? (check status too) $order = getOrderFromInvoiceEvent($pmpro_stripe_event); //no? create it if (empty($order->id)) { //last order for this subscription //getOldOrderFromInvoiceEvent($pmpro_stripe_event); $old_order = new MemberOrder(); $old_order->getLastMemberOrderBySubscriptionTransactionID($pmpro_stripe_event->data->object->subscription); if (empty($old_order)) { $logstr .= "Couldn't find the original subscription."; pmpro_stripeWebhookExit(); } $user_id = $old_order->user_id; $user = get_userdata($user_id); $user->membership_level = pmpro_getMembershipLevelForUser($user_id); if (empty($user)) { $logstr .= "Couldn't find the old order's user. Order ID = " . $old_order->id . "."; pmpro_stripeWebhookExit(); } $invoice = $pmpro_stripe_event->data->object; //alright. create a new order/invoice $morder = new MemberOrder(); $morder->user_id = $old_order->user_id;