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.

Hide Those Private Keys

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.

We already know that our Stripe account has two environments, and each has its own two keys. This means that when we deploy, we'll need to update our code to use these Live keys, instead of the ones from the Test environment.

Well... that's going to be a bummer: the public key is hard-coded right in the middle of my template:

... lines 1 - 3
{% block body %}
<div class="nav-space-checkout">
<div class="container">
<div class="row">
... lines 8 - 34
<div class="col-xs-12 col-sm-6">
<form action="" method="POST">
<script
... line 38
data-key="pk_test_HxZzNHy8LImKK9LDtgMDRBwd"
... lines 40 - 45
</script>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

And the private one is stuck in the center of a controller:

... lines 1 - 10
class OrderController extends BaseController
{
... lines 13 - 30
public function checkoutAction(Request $request)
{
... lines 33 - 34
if ($request->isMethod('POST')) {
... lines 36 - 37
\Stripe\Stripe::setApiKey("XXX_PRIVATEKEY_XXX");
... lines 39 - 49
}
... lines 51 - 56
}
}

If you love editing random files whenever you deploy, then this is perfect! Have fun!

But for the rest of us, we need to move these keys to a central configuration file so they're easy to update on deploy. We also need to make sure that we don't commit this private key to our Git repository... ya know... because it's private - even though I keep showing you mine.

Quick! To a Configuration File!

How you do this next step will vary for different frameworks, but is philosophically always the same. In Symfony, we're going to move our keys to a special parameters.yml file, because our project is setup to not commit this to Git.

Add a stripe_secret_key config and set its value to the key from the controller:

... lines 1 - 3
parameters:
... lines 5 - 19
stripe_secret_key: XXX_PRIVATEKEY_XXX
... lines 21 - 22

Then add stripe_public_key and set that to the one from the template:

... lines 1 - 3
parameters:
... lines 5 - 20
stripe_public_key: YYY_PUBLISHABLE_KEY_YYY

In Symfony, we also maintain this other file - parameters.yml.dist - as a template for the original, uncommitted file. This one is committed to the repository. Add the keys here too, but give them fake values.

Using the Parameters

Now that these are isolated in parameters.yml, we can take them out of our code. In the controller, add $this->getParameter('stripe_secret_key'):

... lines 1 - 11
class OrderController extends BaseController
{
... lines 14 - 31
public function checkoutAction(Request $request)
{
... lines 34 - 35
if ($request->isMethod('POST')) {
... lines 37 - 38
\Stripe\Stripe::setApiKey($this->getParameter('stripe_secret_key'));
... lines 40 - 70
}
... lines 72 - 78
}
}

Next, pass a new stripe_public_key variable to the template set to $this->getParameter('stripe_public_key'):

... lines 1 - 11
class OrderController extends BaseController
{
... lines 14 - 31
public function checkoutAction(Request $request)
{
... lines 34 - 72
return $this->render('order/checkout.html.twig', array(
... lines 74 - 75
'stripe_public_key' => $this->getParameter('stripe_public_key')
));
}
}

Finally, in the template - render that new variable:

... lines 1 - 3
{% block body %}
<div class="nav-space-checkout">
<div class="container">
<div class="row">
... lines 8 - 34
<div class="col-xs-12 col-sm-6">
<form action="" method="POST">
<script
... line 38
data-key="{{ stripe_public_key }}"
... lines 40 - 45
</script>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

Make sure we didn't break anything by finding a product and adding it to the cart. The fact that this "Pay with Card" shows up means things are probably OK.

This was a small step, but don't mess it up! If that secret key becomes not so secret, sheep-zombies guys, sheep-zombies will attack.

Leave a comment!

7
Login or Register to join the conversation

Hello, what is the right file in Symfony4 for fit with the parameters.yml in video (1:08) ?
Thank you !

Reply
Peter Avatar

I was thinking the same thing, its pretty simple.

In the .env.local, I just add two environment variables:

STRIPE_SECRET_KEY=YourCrazyArsedTokenFromStriped_shhhSecret
STRIPE_PUBLIC_KEY=YourCrazyArsedTokenFromStriped_pffttelleveryone

Then in the framework.yml file you just pull them out. :)


stripe_public_key: '%env(STRIPE_PUBLIC_KEY)%'
stripe_private_key: '%env(STRIPE_SECRET_KEY)%'

Now you can just grab them like any other variable from the config files.

Reply

Hey Peter

Thanks for good example, just instead of framework.yml it's better to use config/services.yaml

Cheers!

Reply

hey ojtouch

It depends on what you need to store. For sensitive data(secret keys etc.) you should use .env.local or other env-related files like .env.*.local for other data config/services.yaml or .env, .env.*

Cheers!

Reply

Hello,
I have a problem with my constructer (in StripeClient.php class)

public function __construct(EntityManagerInterface $em)
{
$secretKey = $this->getParameter('stripe_private_key');
\Stripe\Stripe::setApiKey($secretKey);

$this->em = $em;
}

$secretKey return null

I store it here services.yaml
parameters:
locale: 'fr'
stripe_public_key: '%env(STRIPE_PUBLIC_KEY)%'
stripe_private_key: '%env(STRIPE_SECRET_KEY)%'

and in my .env.local
###STRIPE KEYS###
STRIPE_PUBLIC_KEY=pk_test_EaLhidden
STRIPE_SECRET_KEY=sk_test_Aghidden

Can you help me please ?

Thanks

Reply

Hey ojtouch

I'm not sure, because I don't know how your getParameter() works, But in your case, I prefer to use service definition for passing this parameter. For example
in config/services.yaml under services: section define


<your_namespase>\StripeClient:
$secretKey: '%stripe_private_key%'


and change your StripeClient constructor to


public function __construct(EntityManagerInterface $em, string $secretKey)
{
// your code here
}

Hope this will help

Cheers!!

Reply

Thank you sadikoff ! It Works !!

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.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "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", // 1.1.1
        "twig/twig": "^1.24.1", // v1.35.2
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0", // v3.1.2
        "hautelook/alice-bundle": "^1.3", // v1.3.1
        "doctrine/data-fixtures": "^1.2" // v1.2.1
    }
}