Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This course is archived!
This tutorial uses an older version of Symfony of the stripe-php SDK. The majority of the concepts are still valid, though there *are* differences. We've done our best to add notes & comments that describe these changes.

Create those Subscription Plans

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Yes! You're back! You survived Stripe part 1. Ok... that's cool, but now we have bigger fish to fry. So fasten your seat belts, put on a pot of coffee, and get ready to sharpen your Stripe subscription skills.

Wake up the Sheep

To become my best friend, just code along with me! If you coded with part one of the tutorial, you'll need a fresh copy of the code: we made a few tweaks. Download it from this page, unzip it, and then move into the start/ directory.

That'll give you the same code I have here. Open the README file for the setup instructions. The last step will be to open a terminal, move into the project directory, and run:

./bin/console server:run

to start the built-in web server. Now for the magic: pull up the site at http://localhost:8000.

Oh yea, it's the Sheep Shear Club: thanks to part 1, it's already possible to buy individual products. Now, click "Pricing". The real point of the site is to get a subscription that'll send your awesome sheep awesome shearing accessories monthly. After vigorous meetings with our investors, we've decided to offer 2 plans: the Farmer Brent at $99/month and the New Zealander at $199/month. But other than this fancy looking page, we haven't coded anything for this yet.

Tell Stripe about the Plans

Our first step is to tell Stripe about these two plans. To do that, open your trusty Stripe dashboard, make sure you're in the test environment, and find "Plans" on the left. We're going to create the two plans in Stripe by hand. The ID can be any unique string and we'll use this forever after to refer to the plan. Use, farmer_brent_monthly. Then, fill in a name - that's less important and set the price as $99 per month. Create that plan!

And yes, later, we'll add yearly versions of each plan... but one step at a time! Repeat that whole process for the New Zealander: set its ID to new_zealander_monthly, give it a name and set its price and interval. Perfect!

Manage the Plans in Our Code

Now, head back to our code and open the src/AppBundle/Subscription directory. I added two classes to help us stay organized. The first is called SubscriptionHelper:

... lines 1 - 2
namespace AppBundle\Subscription;
class SubscriptionHelper
{
/** @var SubscriptionPlan[] */
private $plans = [];
public function __construct()
{
// todo - add the plans
// $this->plans[] = new SubscriptionPlan(
// 'STRIPE_PLAN_KEY',
// 'OUR PLAN NAME',
// 'PRICE'
// );
}
/**
* @param $planId
* @return SubscriptionPlan|null
*/
public function findPlan($planId)
{
foreach ($this->plans as $plan) {
if ($plan->getPlanId() == $planId) {
return $plan;
}
}
}
}

And as you can see... it's not very helpful... yet. But pretty soon, it will keep track of the two plans we just added. We'll use the second class - SubscriptionPlan:

... lines 1 - 2
namespace AppBundle\Subscription;
class SubscriptionPlan
{
private $planId;
private $name;
private $price;
public function __construct($planId, $name, $price)
{
$this->planId = $planId;
$this->name = $name;
$this->price = $price;
}
public function getPlanId()
{
return $this->planId;
}
public function getName()
{
return $this->name;
}
public function getPrice()
{
return $this->price;
}
}

To hold the data for each plan: the plan ID, name and price. But we won't save these to the database.

In SubscriptionHelper, setup the two plans. For the first, use farmer_brent_monthly for the key, name it Farmer Brent and use 99 as the price:

... lines 1 - 4
class SubscriptionHelper
{
... lines 7 - 9
public function __construct()
{
$this->plans[] = new SubscriptionPlan(
'farmer_brent_monthly',
'Farmer Brent',
99
);
... lines 17 - 22
}
... lines 24 - 36
}

Copy that and repeat the same thing: new_zealander_monthly, New Zealander and 199:

... lines 1 - 4
class SubscriptionHelper
{
... lines 7 - 9
public function __construct()
{
... lines 12 - 17
$this->plans[] = new SubscriptionPlan(
'new_zealander_monthly',
'New Zealander',
199
);
}
... lines 24 - 36
}

Love it! The 2 plans live in Stripe and in our code. Time to make it possible to add these to our cart, and then checkout.

Leave a comment!

10
Login or Register to join the conversation
Sylvain C. Avatar
Sylvain C. Avatar Sylvain C. | posted 1 year ago

Hi devs ! At the end of the tutorial, it's possible to have in the same checkout page one-time payment and Subscription ?
Like phone operators : a mobile phone and a phone subscription ?
Thanks !

Reply

Hey Sylvain,

Yes, sure, why not :) You can just render both ways on the same page. And you can literally use 2 different forms for this, and send each to its own specific endpoint where you will handle whether one-time payment or a subscription.

Cheers!

Reply
Yukako Avatar

Dear Symfonycasts Team,

Stripe v3 has changed so much. I cannot find plans for example on my dashboard.
Please promis to make an update on this course !! Peaaaase 😭😭😭😭

Reply

Hey @Yukako!

Ah, I know! So much has changed! I’d like to re-make this tutorial, but it is not currently high on our priority list. Sorry I can’t be more helpful!

Cheers!

Reply
Vicc V. Avatar
Vicc V. Avatar Vicc V. | posted 2 years ago

Hi, is it possible to have a tutoriel about stripe's subscriptions with Symfony 5 ans the last version ot Stripe ? Stripe's documentation is very complex ! Thank you.

Reply

Hey Vicc V.

Thanks you for your request! I added it to our list, sorry nothing can do more about it. Keep watching!

Cheers!

Reply
Nikolay S. Avatar
Nikolay S. Avatar Nikolay S. | posted 3 years ago

Hello,
Is there any working PayPal bundle for SF5 and tutorial for integrating it?

Reply

Hey Niki,

Not sure about any good bundles - you can easily search on GitHub and see if there're any popular. But in case you're interesting in subscriptions with PayPal - take a look at Braintree payment processor - we use it on SymfonyCasts for handling subscriptions with PayPal.

Unfortunately, we don't have any screencasts about PayPal payments yet, but we do have a course about making credit card payments using Stripe - you can check it out here if you're interested in it: https://symfonycasts.com/sc...

I hope this helps!

Cheers!

Reply
Abdelaziz M. Avatar
Abdelaziz M. Avatar Abdelaziz M. | posted 4 years ago

Hello

I downloaded the code and i worked along with this tutoriel but i had this error:

Attempted to call an undefined method named "addSubscription" of class "AppBundle\Store\ShoppingCart". i

Can you help me assumed i had tow tutoriles stripe_1 and stripe_2
Can i have help!thanks

Reply

Hey Abdelaziz,

Please, open your AppBundle\Store\ShoppingCart class and make sure you have addSubscription() method on it - the error says you don't have one. Or you probably just made a misprint in method name ;)

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial uses an older version of Symfony of the stripe-php SDK. The majority of the concepts are still valid, though there *are* differences. We've done our best to add notes & comments that describe these changes.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9, <7.4",
        "symfony/symfony": "3.1.*", // v3.1.10
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.8
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.2
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.3.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "~2.0.1", // v2.0.1
        "stof/doctrine-extensions-bundle": "^1.2", // v1.2.2
        "stripe/stripe-php": "^3.15", // v3.23.0
        "doctrine/doctrine-migrations-bundle": "^1.1", // v1.2.1
        "phpunit/phpunit": "^5.5", // 5.7.20
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.4
        "symfony/phpunit-bridge": "^3.0", // v3.3.0
        "hautelook/alice-bundle": "^1.3", // v1.4.1
        "doctrine/data-fixtures": "^1.2" // v1.2.2
    }
}
userVoice