From 8acbeb0f389b8f60cc288fa0167a00e387ac4faa Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Thu, 10 Oct 2024 14:23:04 +0100 Subject: [PATCH] Move from Stripe Plans to Prices. No change in functionality. --- classes/Subscription.php | 49 ++++++++++--------- classes/TestStripe.php | 14 +++--- tests/AcceptApiTest.php | 2 +- www/docs/api/hook.php | 6 +-- www/docs/api/update-plan.php | 2 +- www/docs/js/payment.js | 28 +++++------ .../templates/html/api/check.php | 8 +-- .../html/api/subscription_detail.php | 16 +++--- .../templates/html/api/update.php | 14 +++--- 9 files changed, 71 insertions(+), 68 deletions(-) diff --git a/classes/Subscription.php b/classes/Subscription.php index 71ec08dfe3..dfac8bc680 100644 --- a/classes/Subscription.php +++ b/classes/Subscription.php @@ -11,8 +11,8 @@ class Subscription { public $upcoming; public $has_payment_data = false; - private static $plans = ['twfy-1k', 'twfy-5k', 'twfy-10k', 'twfy-0k']; - private static $prices = [2000, 5000, 10000, 30000]; + private static $prices = ['twfy-1k', 'twfy-5k', 'twfy-10k', 'twfy-0k']; + private static $amounts = [2000, 5000, 10000, 30000]; public function __construct($arg) { # User ID @@ -63,9 +63,10 @@ public function __construct($arg) { 'customer.default_source', 'customer.invoice_settings.default_payment_method', 'latest_invoice.payment_intent', - 'schedule.phases.items.plan', + 'schedule.phases.items.price', ], ]); + $this->stripe->price = $this->stripe->items[0]->price; } catch (\Stripe\Exception\InvalidRequestException $e) { $this->db->query('DELETE FROM api_subscription WHERE stripe_id = :stripe_id', [':stripe_id' => $id]); $this->delete_from_redis(); @@ -82,12 +83,12 @@ public function __construct($arg) { $data = $this->stripe; if ($data->discount && $data->discount->coupon && $data->discount->coupon->percent_off) { $this->actual_paid = add_vat(floor( - $data->plan->amount * (100 - $data->discount->coupon->percent_off) / 100 + $data->price->unit_amount * (100 - $data->discount->coupon->percent_off) / 100 )); - $data->plan->amount = add_vat($data->plan->amount); + $data->price->unit_amount = add_vat($data->price->unit_amount); } else { - $data->plan->amount = add_vat($data->plan->amount); - $this->actual_paid = $data->plan->amount; + $data->price->unit_amount = add_vat($data->price->unit_amount); + $this->actual_paid = $data->price->unit_amount; } try { @@ -101,17 +102,17 @@ private function update_subscription($form_data) { $this->update_payment_method($form_data['payment_method']); } - foreach ($this::$plans as $i => $plan) { - if ($plan == $form_data['plan']) { - $new_price = $this::$prices[$i]; + foreach ($this::$prices as $i => $price) { + if ($price == $form_data['price']) { + $new_price = $this::$amounts[$i]; if ($form_data['coupon'] == 'charitable100') { $new_price = 0; } elseif ($form_data['coupon'] == 'charitable50') { $new_price /= 2; } } - if ($plan == $this->stripe->plan->id) { - $old_price = $this::$prices[$i]; + if ($price == $this->stripe->price->id) { + $old_price = $this::$amounts[$i]; if ($this->stripe->discount && ($coupon = $this->stripe->discount->coupon)) { if ($coupon->percent_off == 100) { $old_price = 0; @@ -136,7 +137,7 @@ private function update_subscription($form_data) { 'default_tax_rates' => [STRIPE_TAX_RATE], ], [ - 'items' => [['price' => $form_data['plan']]], + 'items' => [['price' => $form_data['price']]], 'iterations' => 1, 'metadata' => $form_data['metadata'], 'proration_behavior' => 'none', @@ -155,7 +156,7 @@ private function update_subscription($form_data) { if ($old_price < $new_price) { $args = [ 'payment_behavior' => 'allow_incomplete', - 'plan' => $form_data['plan'], + 'items' => [['price' => $form_data['price']]], 'metadata' => $form_data['metadata'], 'cancel_at_period_end' => false, # Needed in Stripe 2018-02-28 'proration_behavior' => 'always_invoice', @@ -212,7 +213,7 @@ private function add_subscription($form_data) { $customer = $obj->id; - if (!$form_data['stripeToken'] && !($form_data['plan'] == $this::$plans[0] && $form_data['coupon'] == 'charitable100')) { + if (!$form_data['stripeToken'] && !($form_data['price'] == $this::$prices[0] && $form_data['coupon'] == 'charitable100')) { exit(1); # Should never reach here! } @@ -221,7 +222,7 @@ private function add_subscription($form_data) { 'expand' => ['latest_invoice.payment_intent'], 'default_tax_rates' => [STRIPE_TAX_RATE], 'customer' => $customer, - 'plan' => $form_data['plan'], + 'items' => [['price' => $form_data['price']]], 'coupon' => $form_data['coupon'], 'metadata' => $form_data['metadata'], ]); @@ -243,21 +244,21 @@ public function invoices() { } private function getFields() { - $fields = ['plan', 'charitable_tick', 'charitable', 'charity_number', 'description', 'tandcs_tick', 'stripeToken', 'payment_method']; + $fields = ['price', 'charitable_tick', 'charitable', 'charity_number', 'description', 'tandcs_tick', 'stripeToken', 'payment_method']; $this->form_data = []; foreach ($fields as $field) { $this->form_data[$field] = get_http_var($field); } } - private function checkValidPlan() { - return ($this->form_data['plan'] && in_array($this->form_data['plan'], $this::$plans)); + private function checkValidPrice() { + return ($this->form_data['price'] && in_array($this->form_data['price'], $this::$prices)); } private function checkPaymentGivenIfNeeded() { $payment_data = $this->form_data['stripeToken'] || $this->form_data['payment_method']; return ($this->has_payment_data || $payment_data || ( - $this->form_data['plan'] == $this::$plans[0] + $this->form_data['price'] == $this::$prices[0] && in_array($this->form_data['charitable'], ['c', 'i']) )); } @@ -271,7 +272,7 @@ public function checkForErrors() { $form_data['charitable'] = ''; } - if (!$this->checkValidPlan()) { + if (!$this->checkValidPrice()) { $errors[] = 'Please pick a plan'; } @@ -306,7 +307,7 @@ public function createOrUpdateFromForm() { $form_data['coupon'] = null; if (in_array($form_data['charitable'], ['c', 'i'])) { $form_data['coupon'] = 'charitable50'; - if ($form_data['plan'] == $this::$plans[0]) { + if ($form_data['price'] == $this::$prices[0]) { $form_data['coupon'] = 'charitable100'; } } @@ -324,8 +325,8 @@ public function createOrUpdateFromForm() { } } - public function redis_update_max($plan) { - preg_match('#^twfy-(\d+)k#', $plan, $m); + public function redis_update_max($price) { + preg_match('#^twfy-(\d+)k#', $price, $m); $max = $m[1] * 1000; $this->redis->set("$this->redis_prefix:max", $max); $this->redis->del("$this->redis_prefix:blocked"); diff --git a/classes/TestStripe.php b/classes/TestStripe.php index 38362b8756..d21ec56136 100644 --- a/classes/TestStripe.php +++ b/classes/TestStripe.php @@ -11,12 +11,14 @@ public function getSubscription($args) { 'coupon' => ['percent_off' => 100], 'end' => null, ], - 'plan' => [ - 'amount' => '2000', - 'id' => 'twfy-1k', - 'nickname' => 'Some calls per month', - 'interval' => 'month', - ], + 'items' => [ [ + 'price' => [ + 'unit_amount' => '2000', + 'id' => 'twfy-1k', + 'nickname' => 'Some calls per month', + 'interval' => 'month', + ], + ] ] 'cancel_at_period_end' => false, 'created' => time(), 'current_period_end' => time(), diff --git a/tests/AcceptApiTest.php b/tests/AcceptApiTest.php index 2f6aa4479a..35d932a429 100644 --- a/tests/AcceptApiTest.php +++ b/tests/AcceptApiTest.php @@ -144,7 +144,7 @@ public function testApiKeySignup() { $page = $this->post_page('key'); $this->assertStringContainsString('Subscribe to a plan', $page); $page = $this->post_page('update-plan', [ - 'plan' => 'twfy-1k', + 'price' => 'twfy-1k', 'charitable_tick' => 'on', 'charitable' => 'c', 'charity_number' => '123456', diff --git a/www/docs/api/hook.php b/www/docs/api/hook.php index 3388c7b7a3..87291d13b6 100644 --- a/www/docs/api/hook.php +++ b/www/docs/api/hook.php @@ -30,7 +30,7 @@ } elseif ($event->type == 'customer.subscription.updated') { $sub = new \MySociety\TheyWorkForYou\Subscription($obj->id); if ($sub->stripe) { - $sub->redis_update_max($obj->plan->id); + $sub->redis_update_max($obj->items[0]->price->id); } } elseif ($event->type == 'invoice.payment_failed' && $obj->billing_reason == 'subscription_cycle' && stripe_twfy_sub($obj)) { $customer = \Stripe\Customer::retrieve($obj->customer); @@ -51,7 +51,7 @@ $sub = new \MySociety\TheyWorkForYou\Subscription($obj->subscription); } if ($sub->stripe) { - $sub->redis_update_max($sub->stripe->plan->id); + $sub->redis_update_max($sub->stripe->items[0]->price->id); } try { # Update the invoice's PaymentIntent and Charge to say it came from TWFY (for CSV export) @@ -83,7 +83,7 @@ function stripe_twfy_sub($invoice) { return false; } $stripe_sub = \Stripe\Subscription::retrieve($invoice->subscription); - return substr($stripe_sub->plan->id, 0, 4) == 'twfy'; + return substr($stripe_sub->items[0]->price->id, 0, 4) == 'twfy'; } function stripe_reset_quota($subscription) { diff --git a/www/docs/api/update-plan.php b/www/docs/api/update-plan.php index ac16c2db8a..58d22a8a63 100644 --- a/www/docs/api/update-plan.php +++ b/www/docs/api/update-plan.php @@ -11,7 +11,7 @@ $errors = []; MySociety\TheyWorkForYou\Utility\Session::start(); -if (get_http_var('plan')) { +if (get_http_var('price')) { if (!Volnix\CSRF\CSRF::validate($_POST)) { print 'CSRF validation failure!'; exit; diff --git a/www/docs/js/payment.js b/www/docs/js/payment.js index 4988043e92..0deabf6b52 100644 --- a/www/docs/js/payment.js +++ b/www/docs/js/payment.js @@ -1,19 +1,19 @@ (function() { -function plan_cost() { - var plan = document.querySelector('input[name=plan]:checked'), +function price_cost() { + var price = document.querySelector('input[name=price]:checked'), ctick = document.getElementById('id_charitable_tick'), charitable = document.querySelector('input[name=charitable]:checked'); - plan = plan ? plan.value : ''; + price = price ? price.value : ''; ctick = ctick ? ctick.checked : ''; charitable = charitable ? charitable.value : ''; var num = 20; - if (plan === 'twfy-5k') { + if (price === 'twfy-5k') { num = 50; - } else if (plan === 'twfy-10k') { + } else if (price === 'twfy-10k') { num = 100; - } else if (plan === 'twfy-0k') { + } else if (price === 'twfy-0k') { num = 300; } if (ctick) { @@ -29,7 +29,7 @@ function plan_cost() { } function need_stripe() { - var num = plan_cost(); + var num = price_cost(); if (num === 0 || document.getElementById('js-payment').getAttribute('data-has-payment-data')) { return false; } @@ -46,11 +46,11 @@ function toggle_stripe() { } } -if (document.getElementById('id_plan_0')) { - document.getElementById('id_plan_0').addEventListener('change', toggle_stripe); - document.getElementById('id_plan_1').addEventListener('change', toggle_stripe); - document.getElementById('id_plan_2').addEventListener('change', toggle_stripe); - document.getElementById('id_plan_3').addEventListener('change', toggle_stripe); +if (document.getElementById('id_price_0')) { + document.getElementById('id_price_0').addEventListener('change', toggle_stripe); + document.getElementById('id_price_1').addEventListener('change', toggle_stripe); + document.getElementById('id_price_2').addEventListener('change', toggle_stripe); + document.getElementById('id_price_3').addEventListener('change', toggle_stripe); document.getElementById('id_charitable_tick').addEventListener('click', function(e) { if (this.checked) { document.getElementById('charitable-qns').style.display = 'block'; @@ -185,8 +185,8 @@ form && form.addEventListener('submit', function(e) { e.preventDefault(); var errors = 0; - var plan = document.querySelector('input[name=plan]:checked'); - errors += err_highlight(document.querySelector('label[for=id_plan_0]'), !plan); + var price = document.querySelector('input[name=price]:checked'); + errors += err_highlight(document.querySelector('label[for=id_price_0]'), !price); var ctick = document.getElementById('id_charitable_tick').checked; var c = document.querySelector('input[name=charitable]:checked'); errors += err_highlight(document.querySelector('label[for=id_charitable_0]'), ctick && !c); diff --git a/www/includes/easyparliament/templates/html/api/check.php b/www/includes/easyparliament/templates/html/api/check.php index 304c3063bc..a690e1998c 100644 --- a/www/includes/easyparliament/templates/html/api/check.php +++ b/www/includes/easyparliament/templates/html/api/check.php @@ -15,12 +15,12 @@ Sorry, your card has been declined. Perhaps you can try another? - stripe->plan) { ?> -

You are subscribing to stripe->plan->nickname ?>, + stripe->price) { ?> +

You are subscribing to stripe->price->nickname ?>, - costing £actual_paid ?>/stripe->plan->interval ?>. + costing £actual_paid ?>/stripe->price->interval ?>. stripe->discount) { ?> - (£stripe->plan->amount ?>/stripe->plan->interval ?> with + (£stripe->price->unit_amount ?>/stripe->price->interval ?> with stripe->discount->coupon->percent_off ?>% discount applied.)

diff --git a/www/includes/easyparliament/templates/html/api/subscription_detail.php b/www/includes/easyparliament/templates/html/api/subscription_detail.php index 8341a7d460..de5122b0ff 100644 --- a/www/includes/easyparliament/templates/html/api/subscription_detail.php +++ b/www/includes/easyparliament/templates/html/api/subscription_detail.php @@ -17,7 +17,7 @@ 0 && $quota_status['count'] > $quota_status['quota']) { ?>

- You have used up your quota for the stripe->plan->interval ?>. + You have used up your quota for the stripe->price->interval ?>. Please upgrade or contact us.

@@ -29,19 +29,19 @@ - stripe->plan) { ?> + stripe->price) { ?> -

Your current plan is stripe->plan->nickname ?>.

+

Your current plan is stripe->price->nickname ?>.

-

It costs you £actual_paid ?>/stripe->plan->interval ?>. +

It costs you £actual_paid ?>/stripe->price->interval ?>. stripe->discount) { ?> - (£stripe->plan->amount ?>/stripe->plan->interval ?> with + (£stripe->price->unit_amount ?>/stripe->price->interval ?> with stripe->discount->coupon->percent_off ?>% discount applied.)

- stripe->schedule->phases[1] && $subscription->stripe->schedule->phases[1]->items[0]->plan->nickname != $subscription->stripe->plan->nickname) { ?> -

You are switching to stripe->schedule->phases[1]->items[0]->plan->nickname ?> at the end of your current period.

+ stripe->schedule->phases[1] && $subscription->stripe->schedule->phases[1]->items[0]->price->nickname != $subscription->stripe->price->nickname) { ?> +

You are switching to stripe->schedule->phases[1]->items[0]->price->nickname ?> at the end of your current period.

stripe->discount && $subscription->stripe->discount->end) { ?> @@ -79,7 +79,7 @@

Your usage

- This stripe->plan->interval ?>: + This stripe->price->interval ?>: 0) { ?> out of diff --git a/www/includes/easyparliament/templates/html/api/update.php b/www/includes/easyparliament/templates/html/api/update.php index 8c76cf29de..dd92899bf6 100644 --- a/www/includes/easyparliament/templates/html/api/update.php +++ b/www/includes/easyparliament/templates/html/api/update.php @@ -49,14 +49,14 @@ function rdio($name, $value, $text, $id, $required = false, $checked = false) {

- -