Intégration Stripe Links dans Symfony : Paiements rapides et sécurisés
Stripe Links est une solution de paiement révolutionnaire qui permet d'accepter des paiements en ligne sans développement complexe. Cette fonctionnalité de Stripe vous permet de créer des liens de paiement personnalisés que vous pouvez partager avec vos clients, leur permettant de payer directement via une page sécurisée.
Qu'est-ce que Stripe Links ?
Stripe Links est une solution "no-code" qui vous permet de :
- Créer des liens de paiement personnalisés en quelques clics
- Accepter des paiements sans intégration technique complexe
- Personnaliser l'expérience avec votre logo et vos couleurs
- Suivre les paiements en temps réel
- Gérer les remboursements facilement
Avantages de Stripe Links
✅ Simplicité : Aucun développement requis
✅ Sécurité : Conformité PCI DSS automatique
✅ Personnalisation : Logo, couleurs, texte personnalisés
✅ Analytics : Suivi détaillé des conversions
✅ Multi-devices : Compatible mobile et desktop
Intégration technique dans Symfony
Bien que Stripe Links soit conçu pour fonctionner sans code, nous allons voir comment l'intégrer dans votre application Symfony pour une expérience utilisateur optimale.
1. Installation des dépendances
# Installation du SDK Stripe
composer require stripe/stripe-php
# Installation des composants Symfony nécessaires
composer require symfony/http-client
composer require symfony/security-bundle
2. Configuration des variables d'environnement
Ajoutez vos clés Stripe dans votre fichier .env
:
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
3. Création du service Stripe
<?php
// src/Service/StripeService.php
namespace App\Service;
use Stripe\Stripe;
use Stripe\PaymentLink;
use Stripe\Exception\ApiErrorException;
class StripeService
{
private string $secretKey;
public function __construct(string $secretKey)
{
$this->secretKey = $secretKey;
Stripe::setApiKey($this->secretKey);
}
public function createPaymentLink(array $data): string
{
try {
$paymentLink = PaymentLink::create([
'line_items' => [
[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => $data['product_name'],
'description' => $data['description'] ?? '',
],
'unit_amount' => $data['amount'] * 100, // Stripe utilise les centimes
],
'quantity' => $data['quantity'] ?? 1,
],
],
'mode' => 'payment',
'success_url' => $data['success_url'],
'cancel_url' => $data['cancel_url'],
'metadata' => [
'order_id' => $data['order_id'] ?? '',
'customer_email' => $data['customer_email'] ?? '',
],
]);
return $paymentLink->url;
} catch (ApiErrorException $e) {
throw new \Exception('Erreur lors de la création du lien de paiement: ' . $e->getMessage());
}
}
public function retrievePaymentLink(string $linkId): PaymentLink
{
return PaymentLink::retrieve($linkId);
}
}
4. Configuration du service
# config/services.yaml
services:
App\Service\StripeService:
arguments:
$secretKey: '%env(STRIPE_SECRET_KEY)%'
5. Création du contrôleur
<?php
// src/Controller/StripeController.php
namespace App\Controller;
use App\Service\StripeService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class StripeController extends AbstractController
{
public function __construct(
private StripeService $stripeService
) {}
#[Route('/create-payment-link', name: 'create_payment_link', methods: ['POST'])]
public function createPaymentLink(Request $request): Response
{
$data = json_decode($request->getContent(), true);
try {
$paymentLink = $this->stripeService->createPaymentLink([
'product_name' => $data['product_name'],
'description' => $data['description'] ?? '',
'amount' => $data['amount'],
'quantity' => $data['quantity'] ?? 1,
'success_url' => $this->generateUrl('payment_success', [], \Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_URL),
'cancel_url' => $this->generateUrl('payment_cancel', [], \Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_URL),
'order_id' => $data['order_id'] ?? uniqid(),
'customer_email' => $data['customer_email'] ?? '',
]);
return $this->json([
'success' => true,
'payment_link' => $paymentLink
]);
} catch (\Exception $e) {
return $this->json([
'success' => false,
'error' => $e->getMessage()
], 400);
}
}
#[Route('/payment/success', name: 'payment_success')]
public function paymentSuccess(Request $request): Response
{
return $this->render('stripe/success.html.twig', [
'session_id' => $request->query->get('session_id')
]);
}
#[Route('/payment/cancel', name: 'payment_cancel')]
public function paymentCancel(): Response
{
return $this->render('stripe/cancel.html.twig');
}
}
6. Templates Twig
{# templates/stripe/payment_form.html.twig #}
{% extends 'base.html.twig' %}
{% block title %}Paiement sécurisé{% endblock %}
{% block body %}
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h3>Paiement sécurisé</h3>
</div>
<div class="card-body">
<form id="payment-form">
<div class="mb-3">
<label for="product_name" class="form-label">Nom du produit</label>
<input type="text" class="form-control" id="product_name" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Montant (€)</label>
<input type="number" class="form-control" id="amount" step="0.01" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Créer le lien de paiement</button>
</form>
<div id="payment-link-result" class="mt-3" style="display: none;">
<div class="alert alert-success">
<h5>Lien de paiement créé !</h5>
<p>Partagez ce lien avec votre client :</p>
<div class="input-group">
<input type="text" id="payment-link-url" class="form-control" readonly>
<button class="btn btn-outline-secondary" type="button" onclick="copyToClipboard()">
Copier
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.getElementById('payment-form').addEventListener('submit', async function(e) {
e.preventDefault();
const formData = {
product_name: document.getElementById('product_name').value,
amount: parseFloat(document.getElementById('amount').value),
description: document.getElementById('description').value
};
try {
const response = await fetch('/create-payment-link', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData)
});
const result = await response.json();
if (result.success) {
document.getElementById('payment-link-url').value = result.payment_link;
document.getElementById('payment-link-result').style.display = 'block';
} else {
alert('Erreur: ' + result.error);
}
} catch (error) {
alert('Erreur lors de la création du lien de paiement');
}
});
function copyToClipboard() {
const urlInput = document.getElementById('payment-link-url');
urlInput.select();
document.execCommand('copy');
alert('Lien copié dans le presse-papiers !');
}
</script>
{% endblock %}
Utilisation pratique
Création d'un lien de paiement
// Dans votre contrôleur
$paymentLink = $this->stripeService->createPaymentLink([
'product_name' => 'Formation Symfony',
'description' => 'Formation complète sur Symfony 7',
'amount' => 299.00,
'quantity' => 1,
'success_url' => 'https://votre-site.com/success',
'cancel_url' => 'https://votre-site.com/cancel',
]);
Personnalisation avancée
// Personnalisation du lien de paiement
$paymentLink = PaymentLink::create([
'line_items' => [
[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => 'Produit Premium',
'images' => ['https://votre-site.com/image.jpg'],
],
'unit_amount' => 5000, // 50€
],
'quantity' => 1,
],
],
'mode' => 'payment',
'success_url' => 'https://votre-site.com/success?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'https://votre-site.com/cancel',
'customer_creation' => 'always',
'allow_promotion_codes' => true,
'billing_address_collection' => 'required',
'shipping_address_collection' => [
'allowed_countries' => ['FR', 'BE', 'CH'],
],
]);
Avantages de cette intégration
Pour les développeurs
- Intégration simple : Moins de 100 lignes de code
- Sécurité garantie : Stripe gère la conformité PCI
- Flexibilité : Personnalisation complète des liens
- Analytics : Suivi détaillé des conversions
Pour les utilisateurs finaux
- Expérience fluide : Interface Stripe optimisée
- Sécurité : Paiements sécurisés par Stripe
- Multi-devices : Compatible mobile et desktop
- Support : Assistance Stripe 24/7
Conclusion
Stripe Links offre une solution parfaite pour intégrer des paiements dans votre application Symfony sans complexité technique. Cette approche vous permet de :
- Démarrer rapidement avec les paiements
- Réduire les coûts de développement
- Améliorer la conversion avec une UX optimisée
- Gagner du temps sur la maintenance
L'intégration présentée dans cet article vous donne le contrôle total sur la création et la gestion de vos liens de paiement, tout en bénéficiant de la robustesse et de la sécurité de Stripe.
Ressources utiles :