Skip to content
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
}
],
"require": {
"laravel/framework": "5.*",
"php": "^7.1.3",
"laravel/framework": "5.*|6.*",
"stripe/stripe-php": "4.*|5.*|6.*"
},
"autoload": {
Expand Down
96 changes: 96 additions & 0 deletions src/Console/Commands/CreateStripeEndpoints.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Gilbitron\Laravel\Spark\Console\Commands;

use Illuminate\Console\Command;
use Laravel\Cashier\Cashier;
use Laravel\Spark\Spark;
use Stripe;

class CreateStripeEndpoints extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'spark:create-stripe-endpoints';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Removes all current endpoints and creates endpoints in Stripe based on the Spark app';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
Stripe\Stripe::setApiKey(config('services.stripe.secret'));

$this->info('Creating endpoints ...');

try {
$this->deleteEndpoints();
$this->createEndpoints();
} catch (\Stripe\Error\InvalidRequest | \Stripe\Exception\InvalidRequest $e) {
$this->error($e->getMessage());
}

$this->info('Finished');
}

/**
* Delete all endpoints in Stripe
*
* @param array $plans
*/
protected function deleteEndpoints()
{
$endpoints =\Stripe\WebhookEndpoint::all();
foreach ($endpoints as $endpoint) {
$this->info('Deleted webhook endpoint:'.$endpoint->url);

$endpoint->delete();
}
}

/**
* Try and create endpoints in Stripe
*
* @param array $plans
*/
protected function createEndpoints()
{
$url = config('app.url').'webhook/stripe';

\Stripe\WebhookEndpoint::create([
'url' => $url,
'enabled_events' => [
'customer.subscription.updated',
'customer.subscription.deleted',
'customer.updated',
'customer.deleted',
'invoice.payment_action_required',
'invoice.payment_succeeded',
'invoice.created',
]
]);

$this->info('Created webhook endpoint:'.$url);
}
}
110 changes: 83 additions & 27 deletions src/Console/Commands/CreateStripePlans.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ class CreateStripePlans extends Command
*/
protected $description = 'Creates plans in Stripe based on the plans defined in Spark';

/**
* Product Stripe IDs
*
* @var array
*/
private $productStripeIds = [];
/**
* Create a new command instance.
*
Expand All @@ -42,6 +48,9 @@ public function handle()
{
Stripe\Stripe::setApiKey(config('services.stripe.secret'));

$this->info('Fetch products...');
$this->fetchProducts();

$this->info('Creating user plans...');
$this->createStripePlans(Spark::$plans);

Expand All @@ -52,47 +61,94 @@ public function handle()
}

/**
* Try and create plans in Stripe
* Try and create product in Stripe
*
* @param array $plans
*/
protected function createStripePlans($plans)
protected function fetchProducts()
{
foreach ($plans as $plan) {
if ($this->planExists($plan)) {
$this->line('Stripe plan ' . $plan->id . ' already exists');
} else {
Stripe\Plan::create([
'id' => $plan->id,
'name' => Spark::$details['product'] . ' ' . $plan->name . ' (' .
Cashier::usesCurrencySymbol() . $plan->price . ' ' . $plan->interval .
')',
'amount' => $plan->price * 100,
'interval' => str_replace('ly', '', $plan->interval),
'currency' => Cashier::usesCurrency(),
'statement_descriptor' => Spark::$details['vendor'],
'trial_period_days' => $plan->trialDays,
]);

$this->info('Stripe plan created: ' . $plan->id);
try {
/** @var \Stripe\Product[] $products */
$products = Stripe\Product::all();
foreach ($products as $product) {
$this->productStripeIds[] = $product->id;
}

$this->info('Fetched products');
} catch (\Stripe\Error\InvalidRequest | \Stripe\Exception\InvalidRequest $e) {
$this->line('Unable to fetch products');
}

}

/**
* Check if a plan already exists
* Create product in Stripe if needed and return the id
*
* @param $plan
* @return bool
* @param array $plans
*/
private function planExists($plan)
protected function getProductId($name = null)
{
$name = $name ?? Spark::$details['product'];

$id = strtolower(str_replace(' ', '-', $name));

$this->info('Creating looking up id for: '.$id);

if (in_array($id, $this->productStripeIds)) {
return $id;
}

$this->info('Creating product: '.$id);

try {
Stripe\Plan::retrieve($plan->id);
return true;
} catch (\Exception $e) {
$product = Stripe\Product::create([
'id' => $id,
'name' => $name,
'statement_descriptor' => Spark::$details['vendor'],
'unit_label' => Spark::$details['unit_label'] ?? null,
'type' => 'service',
]);

$this->productStripeIds[] = $product->id;

$this->info('Stripe product created: ' . $id);
} catch (\Stripe\Error\InvalidRequest | \Stripe\Exception\InvalidRequest $e) {
$this->line('Stripe product ' . $id . ' already exists');
}

return false;
return $id;
}

/**
* Try and create plans in Stripe
*
* @param array $plans
*/
protected function createStripePlans($plans)
{
foreach ($plans as $plan) {
if ($plan->id === 'free') {
$this->line('Skipping free plan, since the "free" plan is handled by Spark internally.');
continue;
}

try {
Stripe\Plan::create([
'id' => $plan->id,
'nickname' => $plan->name,
'product' => $this->getProductId($plan->attribute('product')),
'amount' => $plan->price * 100,
'interval' => str_replace('ly', '', $plan->interval),
'currency' => config('cashier.currency'),
'trial_period_days' => $plan->trialDays,
'billing_scheme' => 'per_unit',
'usage_type' => 'licensed',
]);

$this->info('Stripe plan created: ' . $plan->id);
} catch (\Stripe\Error\InvalidRequest | \Stripe\Exception\InvalidRequest $e) {
$this->line('Stripe plan ' . $plan->id . ' already exists: '.$e->getMessage());
}
}
}
}
3 changes: 2 additions & 1 deletion src/CreateStripePlansServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class CreateStripePlansServiceProvider extends ServiceProvider
{
protected $commands = [
\Gilbitron\Laravel\Spark\Console\Commands\CreateStripePlans::class,
\Gilbitron\Laravel\Spark\Console\Commands\CreateStripeEndpoints::class,
];

/**
Expand All @@ -29,4 +30,4 @@ public function register()
{
$this->commands($this->commands);
}
}
}