fix: fix subscription cancel (#2886)
This commit is contained in:
Binary file not shown.
@@ -13,6 +13,8 @@ steps:
|
||||
ulimit -S unlimited
|
||||
phpdbg -dmemory_limit=4G -qrr vendor/bin/phpunit -c phpunit.xml --log-junit ./results/junit/unit/results${SYSTEM_JOBPOSITIONINPHASE}.xml --coverage-clover ./results/coverage${SYSTEM_JOBPOSITIONINPHASE}.xml --testsuite $TESTSUITE
|
||||
displayName: 'Run unit tests'
|
||||
env:
|
||||
STRIPE_SECRET: $(STRIPE_SECRET)
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
### Fixes:
|
||||
|
||||
* Fix subscription cancel
|
||||
* Fix last consulted contact list
|
||||
* Fix exception in case a user register twice
|
||||
* Fix vcard export with empty gender
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Exception thrown by Stripe.
|
||||
*/
|
||||
class StripeException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Settings;
|
||||
use App\Helpers\DateHelper;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Helpers\InstanceHelper;
|
||||
use App\Exceptions\StripeException;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class SubscriptionsController extends Controller
|
||||
@@ -27,10 +28,15 @@ class SubscriptionsController extends Controller
|
||||
}
|
||||
|
||||
$planId = auth()->user()->account->getSubscribedPlanId();
|
||||
try {
|
||||
$nextBillingDate = auth()->user()->account->getNextBillingDate();
|
||||
} catch (StripeException $e) {
|
||||
$nextBillingDate = trans('app.unknown');
|
||||
}
|
||||
|
||||
return view('settings.subscriptions.account', [
|
||||
'planInformation' => InstanceHelper::getPlanInformationFromConfig($planId),
|
||||
'nextBillingDate' => auth()->user()->account->getNextBillingDate(),
|
||||
'nextBillingDate' => $nextBillingDate,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -118,7 +124,7 @@ class SubscriptionsController extends Controller
|
||||
return redirect()->route('settings.index');
|
||||
}
|
||||
|
||||
auth()->user()->account->subscription(auth()->user()->account->getSubscribedPlanName())->cancelNow();
|
||||
auth()->user()->account->subscriptionCancel();
|
||||
|
||||
return redirect()->route('settings.subscriptions.downgrade.success');
|
||||
}
|
||||
@@ -134,40 +140,16 @@ class SubscriptionsController extends Controller
|
||||
return redirect()->route('settings.index');
|
||||
}
|
||||
|
||||
$stripeToken = $request->input('stripeToken');
|
||||
|
||||
$plan = InstanceHelper::getPlanInformationFromConfig($request->input('plan'));
|
||||
$errorMessage = '';
|
||||
|
||||
try {
|
||||
auth()->user()->account->newSubscription($plan['name'], $plan['id'])
|
||||
->create($stripeToken, [
|
||||
'email' => auth()->user()->email,
|
||||
]);
|
||||
|
||||
return redirect()->route('settings.subscriptions.upgrade.success');
|
||||
} catch (\Stripe\Error\Card $e) {
|
||||
// Since it's a decline, \Stripe\Error\Card will be caught
|
||||
$body = $e->getJsonBody();
|
||||
$err = $body['error'];
|
||||
$errorMessage = trans('settings.stripe_error_card', ['message' => $err['message']]);
|
||||
} catch (\Stripe\Error\RateLimit $e) {
|
||||
// Too many requests made to the API too quickly
|
||||
$errorMessage = trans('settings.stripe_error_rate_limit');
|
||||
} catch (\Stripe\Error\Authentication $e) {
|
||||
// Authentication with Stripe's API failed
|
||||
// (maybe you changed API keys recently)
|
||||
$errorMessage = trans('settings.stripe_error_authentication');
|
||||
} catch (\Stripe\Error\ApiConnection $e) {
|
||||
// Network communication with Stripe failed
|
||||
$errorMessage = trans('settings.stripe_error_api_connection_error');
|
||||
} catch (\Stripe\Error\Base $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
auth()->user()->account
|
||||
->subscribe($request->input('stripeToken'), $request->input('plan'));
|
||||
} catch (StripeException $e) {
|
||||
return back()
|
||||
->withInput()
|
||||
->withErrors($e->getMessage());
|
||||
}
|
||||
|
||||
return back()
|
||||
->withInput()
|
||||
->withErrors($errorMessage);
|
||||
return redirect()->route('settings.subscriptions.upgrade.success');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ use App\Models\Account\ImportJob;
|
||||
use App\Models\Account\Invitation;
|
||||
use App\Services\User\EmailChange;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Exceptions\StripeException;
|
||||
use Lahaxearnaud\U2f\Models\U2fKey;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Requests\ImportsRequest;
|
||||
@@ -178,7 +179,12 @@ class SettingsController
|
||||
$account = auth()->user()->account;
|
||||
|
||||
if ($account->isSubscribed() && ! $account->has_access_to_paid_version_for_free) {
|
||||
$account->subscriptionCancel();
|
||||
try {
|
||||
$account->subscriptionCancel();
|
||||
} catch (StripeException $e) {
|
||||
return redirect()->route('settings.index')
|
||||
->withErrors($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
DB::table('accounts')->where('id', $account->id)->delete();
|
||||
|
||||
@@ -13,8 +13,8 @@ use App\Models\Contact\Debt;
|
||||
use App\Models\Contact\Gift;
|
||||
use App\Models\Contact\Note;
|
||||
use App\Models\Contact\Task;
|
||||
use App\Traits\Subscription;
|
||||
use App\Models\Journal\Entry;
|
||||
use Laravel\Cashier\Billable;
|
||||
use App\Models\Contact\Gender;
|
||||
use App\Models\Contact\Address;
|
||||
use App\Models\Contact\Contact;
|
||||
@@ -45,7 +45,7 @@ use App\Services\Auth\Population\PopulateContactFieldTypesTable;
|
||||
|
||||
class Account extends Model
|
||||
{
|
||||
use Billable;
|
||||
use Subscription;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@@ -532,38 +532,6 @@ class Account extends Model
|
||||
return $isSubscribed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the account has invoices linked to this account.
|
||||
* This was created because Laravel Cashier doesn't know how to properly
|
||||
* handled the case when a user doesn't have invoices yet. This sucks balls.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasInvoices()
|
||||
{
|
||||
$query = DB::table('subscriptions')->where('account_id', $this->id)->count();
|
||||
|
||||
return $query > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next billing date for the account.
|
||||
*
|
||||
* @return string $timestamp
|
||||
*/
|
||||
public function getNextBillingDate()
|
||||
{
|
||||
// Weird method to get the next billing date from Laravel Cashier
|
||||
// see https://stackoverflow.com/questions/41576568/get-next-billing-date-from-laravel-cashier
|
||||
$subscriptions = $this->asStripeCustomer()['subscriptions'];
|
||||
if (count($subscriptions->data) <= 0) {
|
||||
return;
|
||||
}
|
||||
$timestamp = $subscriptions->data[0]['current_period_end'];
|
||||
|
||||
return DateHelper::getShortDate($timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the current account has limitations with her current
|
||||
* plan.
|
||||
@@ -740,48 +708,6 @@ class Account extends Model
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the plan the account is subscribed to.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubscribedPlanId()
|
||||
{
|
||||
$plan = $this->subscriptions()->first();
|
||||
|
||||
if (! is_null($plan)) {
|
||||
return $plan->stripe_plan;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the friendly name of the plan the account is subscribed to.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubscribedPlanName()
|
||||
{
|
||||
$plan = $this->subscriptions()->first();
|
||||
|
||||
if (! is_null($plan)) {
|
||||
return $plan->name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the plan the account is subscribed to.
|
||||
*/
|
||||
public function subscriptionCancel()
|
||||
{
|
||||
$plan = $this->subscriptions()->first();
|
||||
|
||||
if (! is_null($plan)) {
|
||||
return $plan->cancelNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a specific gender of all the contacts in the account with another
|
||||
* gender.
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use App\Helpers\DateHelper;
|
||||
use Laravel\Cashier\Billable;
|
||||
use App\Helpers\InstanceHelper;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Exceptions\StripeException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
trait Subscription
|
||||
{
|
||||
use Billable;
|
||||
|
||||
/**
|
||||
* Process the upgrade payment.
|
||||
*
|
||||
* @param string $stripeToken
|
||||
* @param string $planName
|
||||
* @return bool|string
|
||||
*/
|
||||
public function subscribe(string $stripeToken, string $planName)
|
||||
{
|
||||
$plan = InstanceHelper::getPlanInformationFromConfig($planName);
|
||||
|
||||
return $this->stripeCall(function () use ($stripeToken, $plan) {
|
||||
$this->newSubscription($plan['name'], $plan['id'])
|
||||
->create($stripeToken, [
|
||||
'email' => auth()->user()->email,
|
||||
]);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the plan the account is subscribed to.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubscribedPlanId()
|
||||
{
|
||||
$plan = $this->subscriptions()->first();
|
||||
|
||||
if (! is_null($plan)) {
|
||||
return $plan->stripe_plan;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the friendly name of the plan the account is subscribed to.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getSubscribedPlanName()
|
||||
{
|
||||
$plan = $this->subscriptions()->first();
|
||||
|
||||
if (! is_null($plan)) {
|
||||
return $plan->name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the plan the account is subscribed to.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function subscriptionCancel()
|
||||
{
|
||||
$plan = $this->subscriptions()->first();
|
||||
|
||||
if (! is_null($plan)) {
|
||||
return $this->stripeCall(function () use ($plan) {
|
||||
$plan->cancelNow();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the account has invoices linked to this account.
|
||||
* This was created because Laravel Cashier doesn't know how to properly
|
||||
* handled the case when a user doesn't have invoices yet. This sucks balls.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasInvoices()
|
||||
{
|
||||
$query = DB::table('subscriptions')->where('account_id', $this->id)->count();
|
||||
|
||||
return $query > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next billing date for the account.
|
||||
*
|
||||
* @return string $timestamp
|
||||
*/
|
||||
public function getNextBillingDate()
|
||||
{
|
||||
// Weird method to get the next billing date from Laravel Cashier
|
||||
// see https://stackoverflow.com/questions/41576568/get-next-billing-date-from-laravel-cashier
|
||||
return $this->stripeCall(function () {
|
||||
$subscriptions = $this->asStripeCustomer()['subscriptions'];
|
||||
if (count($subscriptions->data) <= 0) {
|
||||
return '';
|
||||
}
|
||||
$timestamp = $subscriptions->data[0]['current_period_end'];
|
||||
|
||||
return DateHelper::getShortDate($timestamp);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Call stripe.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
private function stripeCall($callback)
|
||||
{
|
||||
try {
|
||||
return $callback();
|
||||
} catch (\Stripe\Error\Card $e) {
|
||||
// Since it's a decline, \Stripe\Error\Card will be caught
|
||||
$body = $e->getJsonBody();
|
||||
$err = $body['error'];
|
||||
$errorMessage = trans('settings.stripe_error_card', ['message' => $err['message']]);
|
||||
Log::error('Stripe card decline error: '.(string) $e, $e->getJsonBody() ?: []);
|
||||
} catch (\Stripe\Error\RateLimit $e) {
|
||||
// Too many requests made to the API too quickly
|
||||
$errorMessage = trans('settings.stripe_error_rate_limit');
|
||||
Log::error('Stripe RateLimit error: '.(string) $e, $e->getJsonBody() ?: []);
|
||||
} catch (\Stripe\Error\InvalidRequest $e) {
|
||||
// Invalid parameters were supplied to Stripe's API
|
||||
$errorMessage = trans('settings.stripe_error_invalid_request');
|
||||
Log::error('Stripe InvalidRequest error: '.(string) $e, $e->getJsonBody() ?: []);
|
||||
} catch (\Stripe\Error\Authentication $e) {
|
||||
// Authentication with Stripe's API failed
|
||||
// (maybe you changed API keys recently)
|
||||
$errorMessage = trans('settings.stripe_error_authentication');
|
||||
Log::error('Stripe Authentication error: '.(string) $e, $e->getJsonBody() ?: []);
|
||||
} catch (\Stripe\Error\ApiConnection $e) {
|
||||
// Network communication with Stripe failed
|
||||
$errorMessage = trans('settings.stripe_error_api_connection_error');
|
||||
Log::error('Stripe ApiConnection error: '.(string) $e, $e->getJsonBody() ?: []);
|
||||
} catch (\Stripe\Error\Base $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
Log::error('Stripe error: '.(string) $e, $e->getJsonBody() ?: []);
|
||||
}
|
||||
|
||||
throw new StripeException($errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ return [
|
||||
'secret' => env('STRIPE_SECRET', null),
|
||||
'webhook' => [
|
||||
'secret' => env('STRIPE_WEBHOOK_SECRET', null),
|
||||
'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"/js/manifest.js": "/js/manifest.js?id=01c8731923a46c30aaed",
|
||||
"/js/app.js": "/js/app.js?id=dd8c96b817caf556399d",
|
||||
"/js/app.js": "/js/app.js?id=3d68d8e1afeb4fc7a5a0",
|
||||
"/css/app-ltr.css": "/css/app-ltr.css?id=365aae28d589d0d77ad5",
|
||||
"/css/app-rtl.css": "/css/app-rtl.css?id=a43b10e7013145aaff1e",
|
||||
"/css/stripe.css": "/css/stripe.css?id=746c8aaac01c56d3cee1",
|
||||
|
||||
@@ -227,6 +227,7 @@ return [
|
||||
'stripe_error_card' => 'Your card was declined. Decline message is: :message',
|
||||
'stripe_error_api_connection' => 'Network communication with Stripe failed. Try again later.',
|
||||
'stripe_error_rate_limit' => 'Too many requests with Stripe right now. Try again later.',
|
||||
'stripe_error_invalid_request' => 'Invalid parameters. Try again later.',
|
||||
'stripe_error_authentication' => 'Wrong authentication with Stripe',
|
||||
|
||||
'import_title' => 'Import contacts in your account',
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
|
||||
<h3>{{ trans('settings.subscriptions_account_current_plan') }}</h3>
|
||||
|
||||
<p>{!! trans('settings.subscriptions_account_current_paid_plan', ['name' => $planInformation['name']]) !!}</p>
|
||||
<p>{!! trans('settings.subscriptions_account_next_billing', ['date' => $nextBillingDate, 'url' => 'settings/subscriptions/downgrade']) !!}</p>
|
||||
<p>{{ trans('settings.subscriptions_account_current_paid_plan', ['name' => $planInformation['name']]) }}</p>
|
||||
<p>{!! trans('settings.subscriptions_account_next_billing', ['date' => $nextBillingDate, 'url' => route('settings.subscriptions.downgrade')]) !!}</p>
|
||||
|
||||
{{-- Only display invoices if the subscription exists or existed --}}
|
||||
@if (auth()->user()->account->hasInvoices())
|
||||
@if (auth()->user()->account->hasStripeId() && auth()->user()->account->hasInvoices())
|
||||
<div class="invoices">
|
||||
<h3>{{ trans('settings.subscriptions_account_invoices') }}</h3>
|
||||
<ul class="table">
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Stripe\Plan;
|
||||
use Stripe\Token;
|
||||
use Stripe\Stripe;
|
||||
use Stripe\Product;
|
||||
use Stripe\ApiResource;
|
||||
use Tests\FeatureTestCase;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Cashier\Subscription;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class AccountSubscriptionTest extends FeatureTestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $stripePrefix = 'cashier-test-';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $productId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $planId;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (! static::$productId) {
|
||||
$this->markTestSkipped('Set STRIPE_SECRET to run this test.');
|
||||
} else {
|
||||
config([
|
||||
'services.stripe.secret' => env('STRIPE_SECRET'),
|
||||
'monica.requires_subscription' => true,
|
||||
'monica.paid_plan_annual_friendly_name' => 'Annual',
|
||||
'monica.paid_plan_annual_id' => 'annual',
|
||||
'monica.paid_plan_annual_price' => 4500,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
if (empty(env('STRIPE_SECRET'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Stripe::setApiVersion('2019-03-14');
|
||||
Stripe::setApiKey(getenv('STRIPE_SECRET'));
|
||||
|
||||
static::$productId = static::$stripePrefix.'product-1'.Str::random(10);
|
||||
static::$planId = static::$stripePrefix.'monthly-10-'.Str::random(10);
|
||||
|
||||
Product::create([
|
||||
'id' => static::$productId,
|
||||
'name' => 'Monica Test Product',
|
||||
'type' => 'service',
|
||||
]);
|
||||
|
||||
Plan::create([
|
||||
'id' => static::$planId,
|
||||
'nickname' => 'Annual',
|
||||
'currency' => 'USD',
|
||||
'interval' => 'year',
|
||||
'billing_scheme' => 'per_unit',
|
||||
'amount' => 4500,
|
||||
'product' => static::$productId,
|
||||
]);
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass(): void
|
||||
{
|
||||
parent::tearDownAfterClass();
|
||||
|
||||
if (static::$planId) {
|
||||
static::deleteStripeResource(new Plan(static::$planId));
|
||||
}
|
||||
if (static::$productId) {
|
||||
static::deleteStripeResource(new Product(static::$productId));
|
||||
}
|
||||
}
|
||||
|
||||
protected static function deleteStripeResource(ApiResource $resource)
|
||||
{
|
||||
try {
|
||||
$resource->delete();
|
||||
} catch (InvalidRequest $e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
public function test_it_throw_an_error_on_subscribe()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
$this->expectException(\App\Exceptions\StripeException::class);
|
||||
$user->account->subscribe('xxx', 'annual');
|
||||
}
|
||||
|
||||
public function test_it_get_the_plan_name()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
factory(Subscription::class)->create([
|
||||
'account_id' => $user->account_id,
|
||||
'name' => 'Annual',
|
||||
'stripe_plan' => 'annual',
|
||||
'stripe_id' => 'test',
|
||||
'quantity' => 1,
|
||||
]);
|
||||
|
||||
$this->assertEquals('Annual', $user->account->getSubscribedPlanName());
|
||||
}
|
||||
|
||||
public function test_it_get_next_billing_date()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
factory(Subscription::class)->create([
|
||||
'account_id' => $user->account_id,
|
||||
'name' => 'Annual',
|
||||
'stripe_plan' => 'annual',
|
||||
'stripe_id' => 'test',
|
||||
'quantity' => 1,
|
||||
]);
|
||||
|
||||
$this->expectException(\App\Exceptions\StripeException::class);
|
||||
$user->account->getNextBillingDate();
|
||||
}
|
||||
|
||||
public function test_it_throw_an_error_on_cancel()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
factory(Subscription::class)->create([
|
||||
'account_id' => $user->account_id,
|
||||
'name' => 'Annual',
|
||||
'stripe_plan' => 'annual',
|
||||
'stripe_id' => 'test',
|
||||
'quantity' => 1,
|
||||
]);
|
||||
|
||||
$this->expectException(\App\Exceptions\StripeException::class);
|
||||
$user->account->subscriptionCancel();
|
||||
}
|
||||
|
||||
public function test_it_get_subscription_page()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
factory(Subscription::class)->create([
|
||||
'account_id' => $user->account_id,
|
||||
'name' => 'Annual',
|
||||
'stripe_plan' => 'annual',
|
||||
'stripe_id' => 'sub_X',
|
||||
'quantity' => 1,
|
||||
]);
|
||||
|
||||
$response = $this->get('/settings/subscriptions');
|
||||
|
||||
$response->assertSee('You are on the Annual plan. Thanks so much for being a subscriber.');
|
||||
}
|
||||
|
||||
public function test_it_subscribe()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
$response = $this->post('/settings/subscriptions/processPayment', [
|
||||
'stripeToken' => $this->getTestToken(),
|
||||
'plan' => 'annual',
|
||||
]);
|
||||
|
||||
$response->assertRedirect('/settings/subscriptions/upgrade/success');
|
||||
}
|
||||
|
||||
public function test_it_subscribe_with_error()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
$response = $this->post('/settings/subscriptions/processPayment', [
|
||||
'stripeToken' => 'bad',
|
||||
'plan' => 'annual',
|
||||
], [
|
||||
'HTTP_REFERER' => 'back',
|
||||
]);
|
||||
|
||||
$response->assertRedirect('/back');
|
||||
}
|
||||
|
||||
public function test_it_does_not_subscribe()
|
||||
{
|
||||
$user = $this->signin();
|
||||
|
||||
try {
|
||||
$user->account->subscribe($this->getTestTokenError(), 'annual');
|
||||
} catch (\App\Exceptions\StripeException $e) {
|
||||
$this->assertEquals('Your card was declined. Decline message is: Your card was declined.', $e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
$this->fails();
|
||||
}
|
||||
|
||||
protected function getTestToken()
|
||||
{
|
||||
return Token::create([
|
||||
'card' => [
|
||||
'number' => '4242424242424242',
|
||||
'exp_month' => 5,
|
||||
'exp_year' => date('Y') + 1,
|
||||
'cvc' => '123',
|
||||
],
|
||||
])->id;
|
||||
}
|
||||
|
||||
protected function getTestTokenError()
|
||||
{
|
||||
return Token::create([
|
||||
'card' => [
|
||||
'number' => '4000000000009979',
|
||||
'exp_month' => 5,
|
||||
'exp_year' => date('Y') + 1,
|
||||
'cvc' => '123',
|
||||
],
|
||||
])->id;
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,6 @@ class RegisterTest extends FeatureTestCase
|
||||
|
||||
$response = $this->post('/register', $params);
|
||||
|
||||
$response->dump();
|
||||
$response->assertStatus(302);
|
||||
$response->assertRedirect('/dashboard');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user