# Accepter les paiements pour les produits numériques sur iOS avec Stripe comme marchand attitré Ouvrez Stripe Checkout avec Managed Payments dans un navigateur pour vendre des produits ou des abonnements numériques intégrés à une application. > #### Conditions d'utilisation du service requises > > You must accept the [Managed Payments terms of service](https://stripe.com/legal/managed-payments) in the [Dashboard](https://dashboard.stripe.com/settings/managed-payments) before you can use Managed Payments. Dans [certains pays](https://support.stripe.com/questions/changes-to-ios-app-store-guidelines), vous pouvez créer un lien vers un site web externe pour accepter des paiements en utilisant Managed Payments sur iOS. Vous utilisez [Stripe Checkout](https://docs.stripe.com/payments/checkout.md) pour rediriger vos clients vers une page de paiement hébergée par Stripe. À titre d’exemple, ce guide décrit comment vendre des crédits numériques à utiliser dans votre application. Vous pouvez accepter à la fois des paiements uniques et des paiements par abonnement. ![Paiement ponctuel](https://b.stripecdn.com/docs-statics-srv/assets/one-time-hero.36361064aef1a09b8192ef17b0b557de.png) L’interface utilisateur que les clients voient pour les paiements uniques avec Managed Payments ![Paiement récurrent](https://b.stripecdn.com/docs-statics-srv/assets/recurring-hero.00968928fbe5564c9964922965c8b3c1.png) L’interface utilisateur que les clients voient pour les paiements d’abonnement avec Managed Payments ## Mode de fonctionnement Le diagramme suivant illustre le tunnel de paiement complet d’une application au web à un niveau élevé : Tunnel de paiement de haut niveau d’une application au web pour les achats in-app (See full diagram at https://docs.stripe.com/payments/managed-payments/set-up-mobile) ## Limitations Ce guide ne couvre pas : - L’authentification de l’utilisateur. Si vous ne disposez pas encore d’un fournisseur d’authentification, vous pouvez faire appel à un tiers (par exemple, avec l’option [Se connecter avec Apple](https://developer.apple.com/sign-in-with-apple/) ou [Authentification Firebase](https://firebase.google.com/docs/auth)). - Les achats intégrés à l’application. Pour implémenter des achats dans l’application avec StoreKit, consultez le [guide d’Apple sur les achats intégrés à l’application](https://developer.apple.com/in-app-purchase/). Ce guide ne décrit que le processus de vente de produits numériques intégrés à une application qui respectent ces [critères d’éligibilité](https://docs.stripe.com/payments/managed-payments/eligibility.md). Si vos produits numériques ne correspondent pas à ces critères, consultez la section [Accepter les paiements pour les biens numériques sur iOS](https://docs.stripe.com/mobile/digital-goods/checkout.md). Si vous vendez des produits physiques, consultez la section [Paiements Stripe intégrés à une application](https://docs.stripe.com/payments/mobile.md). ## Before you begin - Assurez-vous que vos produits respectent les [critères d’éligibilité](https://docs.stripe.com/payments/managed-payments/eligibility.md) pour Managed Payments. Pour traiter un paiement avec Managed Payments, tous les produits que le client achète doivent être éligibles. - Activez Managed Payments dans votre [Dashboard](https://dashboard.stripe.com/settings/managed-payments) - [Configurez votre environnement de développement](https://docs.stripe.com/get-started/development-environment.md). - Utilisez une version d’API `2025-03-31.basil` ou [ultérieure](https://docs.stripe.com/changelog.md). ## Créer des produits et tarifs Créez vos *produits* (Products represent items your customer can subscribe to with a Subscription. An associated Price object describes the pricing and other terms of the subscription) et leurs *tarifs* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions) dans le Dashboard ou avec la CLI de Stripe. Vous pouvez ajouter des produits numériques avec des tarifs uniques et des abonnements avec des tarifs récurrents. Vous pouvez également laisser votre client payer le montant de son choix (par exemple, pour décider du nombre de crédits à acheter), en sélectionnant **Les clients choisissent ce qu’ils paient**. Lorsque vous créez votre produit, le code fiscal que vous sélectionnez doit être [éligible à Managed Payments](https://docs.stripe.com/payments/managed-payments/eligibility.md#eligible-tax-codes). Les codes fiscaux éligibles sont libellés `Eligible for Managed Payments`. Cet exemple utilise un seul *produit* et un seul *tarif* pour représenter un lot de 100 pièces qui coûte 10 USD. #### Dashboard Allez à la page [Ajouter un produit](https://dashboard.stripe.com/test/products/create) et créez le lot de pièces. Ajoutez un prix unique de 10 USD. Sélectionnez `txcd_10201000`for the tax code `Video Games - downloaded - non subscription - with permanent rights tax code`. - 100 coins : pack de 100 coins dans l’application - Tarif : Modèle standard | 10 USD | Paiement unique | txcd_10201000 Après avoir créé le tarif, enregistrez l’ID du tarif pour pouvoir l’utiliser dans les étapes suivantes. Les ID de tarif sont similaires à : `price_G0FvDp6vZvdwRZ`. Lorsque vous êtes prêt(e), cliquez sur **Copier en mode production** pour cloner votre produit d’un [environnement de test vers le mode production](https://docs.stripe.com/keys.md#test-live-modes). #### Interface de ligne de commande Stripe Ensuite, créez les objets produit : ```bash stripe products create \ --name="100 coins" \ --description="Bundle of 100 in-app coins" \ --tax-code="txcd_10201000" ``` L’interface de ligne de commande Stripe renvoie les informations sur le produit, dont son ID. ```json { "id": "prod_H94k5odtwJXMtQ", "object": "product", "active": true, "attributes": [ ], "created": 1587577341, "description": "Bundle of 100 in-app coins", "images": [ ], "livemode": false, "metadata": { }, "name": "100 coins", "statement_descriptor": null, "tax_code": "txcd_10201000", "type": "service", "unit_label": null, "updated": 1587577341 } ``` Utilisez l’ID du produit pour créer un tarif. Le nombre de l’`unit_amount` est en centimes, donc `1000` équivaut à 10 USD, par exemple. ```bash stripe prices create \ -d product=prod_H94k5odtwJXMtQ \ -d unit_amount=1000 \ -d currency=usd ``` Enregistrez l’ID de tarif pour chaque tarif afin de pouvoir les utiliser dans les étapes suivantes. Ils ressemblent à ceci : ```json { "id": "price_1Jh0tjEmNk5jCjFGCkLnNYGO", "object": "price", "active": true, "billing_scheme": "per_unit", "created": 1633391323, "currency": "usd", "livemode": false, "lookup_key": null, "metadata": { }, "nickname": null, "product": "prod_H94k5odtwJXMtQ", "recurring": null, "tax_behavior": "unspecified", "tiers_mode": null, "transform_quantity": null, "type": "one_time", "unit_amount": 1000, "unit_amount_decimal": "1000" } ``` ## Créer des clients [Côté serveur] Chaque fois que vous créez une session Checkout, créez un objet *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) pour votre utilisateur si celui-ci n’existe pas encore. #### Node.js ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. // Find your keys at https://dashboard.stripe.com/apikeys. const stripe = require('stripe')('<>'); // This assumes your app has an existing user database, which we'll call `myUserDB`. const user = myUserDB.getUser("jennyrosen"); if (!user.stripeCustomerID) { const customer = await stripe.customers.create({ name: user.name, email: user.email, }); // Set the user's Stripe Customer ID for later retrieval. user.stripeCustomerID = customer.id; } ``` > Veillez à conserver sur votre serveur l’association entre le compte d’utilisateur et l’ID de client Stripe. Sans cela, vous ne pourrez pas associer vos clients à des achats et vos clients ne pourront donc pas récupérer leurs achats. > > Si votre application ne dispose pas de fournisseur d’authentification, vous pouvez utiliser l’option [Se connecter avec Apple](https://developer.apple.com/sign-in-with-apple/). Utilisez l’argument [customer](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer) pour passer son ID client lors de la création d’une session Checkout. Cela garantit que tous les objets créés pendant la session s’associent au bon objet `Customer`. ## Configurer des liens universels [Côté client] [Côté serveur] Les *liens universels* (Use Universal links on iOS and macOS to link directly to in-app content. They're standard HTTPS links, so the same URL works for your website and your app) autorisent Checkout à vous renvoyer directement vers votre application. Pour configurer un lien universel : 1. Ajoutez un fichier `apple-app-site-association` à votre domaine. 1. Ajoutez une autorisation de domaines associés à votre application. 1. Ajoutez une page de renvoi pour vos URL de redirection Checkout. #### Définissez les domaines associés Ajoutez un fichier à votre domaine sur **.well-known/apple-app-site-association** pour définir les URL que votre application peut gérer. Ajoutez l’ID d’application avec votre ID d’équipe que vous pourrez trouver sur la [page d’abonnement du portail développeur d’Apple](https://developer.apple.com/account). ```json { "applinks": { "apps": [], "details": [ { "appIDs": [ "A28BC3DEF9.com.example.MyApp1", "A28BC3DEF9.com.example.MyApp1-Debug" ], "components": [ { "/": "/checkout_redirect*", "comment": "Matches any URL whose path starts with /checkout_redirect" } ] } ] } } ``` Vous devez traiter le fichier avec le type MIME `application/json`. Utilisez `curl -I` pour confirmer le type de contenu. ```bash curl -I https://example.com/.well-known/apple-app-site-association ``` Pour en savoir plus, consultez la page d’Apple relative aux [domaines associés pris en charge](https://developer.apple.com/documentation/xcode/supporting-associated-domains). #### Ajouter un droit de domaine associé à votre application 1. Ouvrez le volet **Signatures et fonctionnalités** de la cible de votre application. 1. Cliquez sur **+ Fonctionnalité**, puis sélectionnez **Domaines associés**. 1. Ajoutez une entrée pour `applinks:example.com` à la liste **Domaines associés**. Pour en savoir plus sur les liens universels, consultez la page d’Apple sur les [liens universels pour les développeurs](https://developer.apple.com/ios/universal-links/). Bien qu’iOS intercepte les liens vers les URL définies dans votre fichier `apple-app-site-association`, il se peut que la redirection ne parvienne pas à ouvrir votre application. Assurez-vous de créer une [page de repli](https://docs.stripe.com/payments/checkout/custom-success-page.md?payment-ui=stripe-hosted) à votre `success_url`. Par exemple, vous pouvez [définir un schéma d’URL personnalisé pour votre application](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) et l’utiliser pour créer un lien de retour en cas d’échec du lien universel. ## Créer une session Checkout [Côté serveur] Une [session Checkout](https://docs.stripe.com/api/checkout/sessions/create.md) est la représentation programmatique de ce que votre client voit lorsqu’il est redirigé vers le formulaire de paiement. Les sessions Checkout expirent 24 heures après leur création. Configurez-le à l’aide des éléments suivants : - ID du client - L’ID du produit (soit un paiement unique, soit un abonnement) - Un `origin_context` défini sur `mobile_app` pour opter pour une interface utilisateur optimisée pour les achats de type application vers web. - Le paramètre `managed_payments[enabled]` sur `true` - Une URL `success_url`, à savoir un *lien universel* (Use Universal links on iOS and macOS to link directly to in-app content. They're standard HTTPS links, so the same URL works for your website and your app) vers lequel rediriger votre client après avoir finalisé le paiement. Après avoir créé une session Checkout, renvoyez l’[URL](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-url) contenue dans la réponse vers votre application. #### Paiement ponctuel #### Node.js ```javascript // This example sets up an endpoint using the Express framework. const express = require('express'); const app = express(); // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require('stripe')('<>'); app.post('/create-checkout-session', async (req, res) => { // Fetch the Stripe customer ID for the customer associated with this request. // This assumes your app has an existing user database, which we'll call `myUserDB`. const user = myUserDB.getUserFromToken(req.query.token); const customerId = user.stripeCustomerID; // The price ID from the previous step const priceId = '{{PRICE_ID}}'; const session = await stripe.checkout.sessions.create({ line_items: [ { price: priceId, quantity: 1, }, ], mode: 'payment', managed_payments: {enabled: true}, origin_context: 'mobile_app', customer: customerId, success_url: 'https://example.com/checkout_redirect/success', }); res.json({url: session.url}); }); app.post('/login', async (req, res) => { // This assumes your app has an existing user database, which we'll call `myUserDB`. const token = myUserDB.login(req.body.login_details) res.json({token: token}) }); app.listen(4242, () => console.log(`Listening on port ${4242}!`)); ``` #### Abonnement #### Node.js ```javascript // This example sets up an endpoint using the Express framework. const express = require('express'); const app = express(); // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require('stripe')('<>'); app.post('/create-checkout-session', async (req, res) => {// Fetch the Stripe customer ID for the customer associated with this request. // This assumes your app has an existing user database, which we'll call `myUserDB`. const user = myUserDB.getUserFromToken(req.query.token); const customerId = user.stripeCustomerID; // The price ID from the previous step const priceId = '{{SUBSCRIPTION_PRICE_ID}}'; const session = await stripe.checkout.sessions.create({ line_items: [ { price: priceId, quantity: 1, }, ], mode: 'subscription', managed_payments: {enabled: true}, origin_context: 'mobile_app', customer: customerId, success_url: 'https://example.com/checkout_redirect/success', }); res.json({url: session.url}); }); app.post('/login', async (req, res) => { // This assumes your app has an existing user database, which we'll call `myUserDB`. const token = myUserDB.login(req.body.login_details) res.json({token: token}) }); app.listen(4242, () => console.log(`Listening on port ${4242}!`)); ``` ## Ouvrir Checkout dans Safari [Côté client] Ajoutez un bouton de paiement à votre application. Ce bouton : 1. Appelez un endpoint côté serveur pour créer une session Checkout. 1. Renvoie la session Checkout au client. 1. Ouvre l’URL de la session dans Safari. ```swift import Foundation import SwiftUI import StoreKit struct BuyCoinsView: View { @EnvironmentObject var myBackend: MyServer @State var paymentComplete = false var body: some View { // Check if payments are blocked by Parental Controls on this device. if !SKPaymentQueue.canMakePayments() { Text("Payments are disabled on this device.") } else { if paymentComplete { Text("Payment complete!") } else { Button { myBackend.createCheckoutSession { url in UIApplication.shared.open(url, options: [:], completionHandler: nil) } } label: { Text("Buy 100 coins") }.onOpenURL { url in // Handle the universal link from Checkout. if url.absoluteString.contains("success") { // The payment was completed. Show a success // page and fetch the latest customer entitlements // from your server. paymentComplete = true } } } } } } ``` ### Récupérer l’URL Checkout côté client Utilisez votre endpoint serveur pour récupérer la session de paiement. ```swift class MyServer: ObservableObject { // The cached login token var token: String? func createCheckoutSession(completion: @escaping (URL) -> Void) { // Send the login token to the `/create_checkout_session` endpoint let request = URLRequest(url: URL(string: "https://example.com/create-checkout-session?token=\(self.token)")!) let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in guard let unwrappedData = data, let json = try? JSONSerialization.jsonObject(with: unwrappedData, options: []) as? [String : Any], let urlString = json["url"] as? String, let url = URL(string: urlString) else { // Handle error return } DispatchQueue.main.async { // Call the completion block with the Checkout session URL returned from the backend completion(url) } }) task.resume() } func login() { // Login using the server and set the login token. let request = URLRequest(url: URL(string: "https://example.com/login")!) let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in guard let unwrappedData = data, let json = try? JSONSerialization.jsonObject(with: unwrappedData, options: []) as? [String : Any], let token = json["token"] as? String else { // Handle error return } self.token = token }) task.resume() } } ``` ## Gérer le traitement des commandes [Côté serveur] Une fois l’achat effectué, Stripe vous envoie un *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) `checkout.session.completed`. Lorsque vous l’avez reçu, vous pouvez ajouter les coins au client sur votre serveur. Checkout redirige votre client vers l’URL `success_url` lorsque vous [confirmez avoir reçu l’événement](https://docs.stripe.com/webhooks.md#acknowledge-events-immediately). Si votre endpoint est hors service ou si l’événement n’est pas confirmé correctement, Checkout redirige le client vers l’URL `success_url` 10 secondes après la finalisation du paiement. Pour les tests, vous pouvez surveiller les événements dans le [Dashboard](https://dashboard.stripe.com/events) ou utiliser l’[interface de ligne de commande Stripe](https://docs.stripe.com/webhooks.md#test-webhook). Pour le mode production, configurez un endpoint de webhook et abonnez-vous aux types d’événement appropriés. Si vous ne connaissez pas votre clé `STRIPE_WEBHOOK_SECRET`, cliquez sur le [webhook](https://dashboard.stripe.com/webhooks) dans le Dashboard pour l’afficher. #### Node.js ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. // Find your keys at https://dashboard.stripe.com/apikeys. const stripe = require('stripe')('<>'); app.post("/webhook", async (req, res) => { let data; let eventType; // Check if webhook signing is configured. const webhookSecret = "{{STRIPE_WEBHOOK_SECRET}}" // Exemple : whsec_c7681Dm if (webhookSecret) { // Retrieve the event by verifying the signature using the raw body and secret. let event; let signature = req.headers["stripe-signature"]; try { event = stripe.webhooks.constructEvent( req.body, signature, webhookSecret ); } catch (err) { console.log(`⚠️ Webhook signature verification failed.`); return res.sendStatus(400); } // Extract the object from the event. data = event.data; eventType = event.type; } else { // Webhook signing is recommended, but if the secret is not configured in `config.js`, // retrieve the event data directly from the request body. data = req.body.data; eventType = req.body.type; } switch (eventType) { case 'checkout.session.completed': const session = event.data.object; // Payment is successful. // Update the customer in your database to reflect this purchase. const user = myUserDB.userForStripeCustomerID(session.customer); user.addCoinsTransaction(100, session.id); break; default: // Unhandled event type } res.sendStatus(200); }); ``` ### Tests Testez votre bouton de paiement qui redirige votre client vers Stripe Checkout. 1. Cliquez sur le bouton de paiement qui vous redirige vers le formulaire de paiement Stripe Checkout. 1. Saisissez le numéro de carte de test 4242 4242 4242 4242, un code CVC à trois chiffres, une date d’expiration et un code postal valide. 1. Appuyez sur **Payer**. 1. Le webhook `checkout.session.completed` s’active et Stripe notifie votre serveur de la transaction. 1. Vous êtes redirigé(e) vers votre application. Si votre intégration ne fonctionne pas, consultez la section [Ressources de test supplémentaires](https://docs.stripe.com/payments/managed-payments/set-up-mobile.md#additional-testing-resources) ci-dessous. ### Détails du paiement #### Item 1 1. Après avoir confirmé le paiement test, accédez au **Dashboard** > [Transactions](https://dashboard.stripe.com/test/payments) 1. Cliquez sur votre paiement test pour afficher les détails du paiement. Cette page affiche : - Produit acheté - [Abonnement](https://docs.stripe.com/api/subscriptions.md) créé - [Facture](https://docs.stripe.com/api/invoices.md) créée - Montant des taxes calculées et retenues via Managed Payments - Libellé de relevé bancaire qui s’affiche sur les relevés de votre client > #### Autorisation client > > Lorsqu’un client achète un abonnement via Managed Payments, il autorise uniquement son moyen de paiement à être débité par Managed Payments. Assurez-vous d’obtenir le consentement approprié de votre client pour débiter ce moyen de paiement pour toute transaction en dehors de Managed Payments. #### Item 2 1. Après avoir confirmé le paiement test, accédez au **Dashboard** > [Transactions](https://dashboard.stripe.com/test/payments). 1. Cliquez sur votre paiement test pour afficher les détails du paiement. Cette page affiche : - Produit acheté - [Abonnement](https://docs.stripe.com/api/subscriptions.md) créé (si acheté) - [Facture](https://docs.stripe.com/api/invoices.md) créée - Montant des taxes calculées et retenues via Managed Payments - Libellé de relevé bancaire qui s’affiche sur les relevés de votre client #### Aperçu du reçu 1. Sous **Historique des reçus**, cliquez sur **Afficher le reçu**. 1. Cliquez sur **Envoyer reçu** pour avoir un aperçu du reçu envoyé par e-mail à votre client. > Dans l’environnement de test, vous ne recevez pas automatiquement les reçus par e-mail après un achat. Envoyez-les manuellement en suivant les instructions ci-dessus. ### Link [Link](https://docs.stripe.com/payments/link.md) agit en tant que marchand officiel lors du paiement et propose la gestion des abonnements ainsi qu’un support pour les transactions sur le site [Link](https://link.com). Vous pouvez tester le fonctionnement de Link au moment du paiement en créant un compte Link lors d’une Checkout Session initiale. Après avoir créé le compte Link, tentez une autre session en utilisant la même adresse e-mail. Pour vous identifier, utilisez le code d’accès de test `000000`. Les achats de test n’apparaîtront pas dans l’application Link. Vous pouvez tester les outils de gestion des commande dans l’application Link en créant un compte Link pendant une Checkout Session en mode production. ## Optional: Ressources de test supplémentaires Stripe met à votre disposition plusieurs cartes de test que vous pouvez utiliser pour vous assurer que votre intégration est prête à passer en production. Utilisez-les avec n’importe quels code CVC, code postal et date d’expiration future. | Numéro | Description | | ------------------- | ----------------------------------------------------------------------------------- | | 4242 4242 4242 4242 | Fait aboutir le paiement et le traite immédiatement. | | 4000 0000 0000 3220 | Effectue une authentification 3D Secure 2 pour que le paiement aboutisse. | | 4000 0000 0000 9995 | Échec systématique avec le code de refus de paiement `insufficient_funds`. | Pour obtenir la liste complète des cartes de test, consultez notre guide consacré aux [tests](https://docs.stripe.com/testing.md). ### Tester des liens universels Si votre lien universel ne vous renvoie pas vers votre application depuis Checkout, vérifiez que les logs `SharedWebCredentials` ne contiennent pas d’erreurs. 1. Ajouter un paramètre de débogage au droit de domaine associé - Ouvrez le volet **Signatures et fonctionnalités** de la cible de votre application. - Ajoutez le flag `?mode=developer` dans votre saisie pour votre domaine associé. *(Exemple : `applinks:example.com?mode=developer`)* 1. Passez l’appareil en mode développeur. - Exécutez une application de Xcode sur votre appareil pour activer le menu développeur. - Sur votre iPhone, ouvrez le volet **Réglages**, touchez **Développeur**, puis activez **Développement des domaines associés**. 1. Supprimez et désinstallez votre application. De cette manière, iOS récupérera à nouveau le fichier apple-app-site-association. 1. Finalisez le tunnel de paiement dans votre application. 1. Checkout vous redirige vers votre application. Si ce n’est pas le cas, lancez un diagnostic système. 1. Appuyez simultanément sur les boutons d’augmentation du volume, de réduction du volume et de marche/arrêt pendant 1 seconde, puis relâchez-les. Vous sentirez une courte vibration, mais aucun élément visuel ne s’affichera. 1. Patientez 5 minutes, puis accédez à **Paramètres** > **Confidentialité** > **Analyses et Amélioration** > **Données d’analyse**. Ensuite, faites défilez la page jusqu’au dernier fichier de diagnostic système de la liste. 1. Touchez le bouton de partage pour envoyer le fichier avec AirDrop sur votre ordinateur. 1. Ouvrez l’archive du diagnostic système, puis le fichier `swcutil_show.txt` 1. Recherchez l’ID de votre application dans ce fichier. Vous verrez une section contenant des informations de débogage pour votre application, dont un message d’erreur, le cas échéant. ``` Service: applinks App ID: Y28TH9SHX7.com.stripe.FruitStore App Version: 1.0 App PI: { v = 0, t = 0x8, u = 0xc98, db = E335D78F-D49E-4F19-A150-F657E50DEDAE, {length = 8, bytes = 0x980c000000000000} } Domain: example.com?mode=developer User Approval: unspecified Site/Fmwk Approval: unspecified Flags: developer Last Checked: 2021-09-23 18:16:58 +0000 Next Check: 2021-09-23 21:21:34 +0000 Error: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0., NSJSONSerializationErrorIndex=0} Retries: 1 ``` ## See also - [Ajouter des réductions](https://docs.stripe.com/payments/checkout/discounts.md) - [Personnaliser l’adaptation à votre marque](https://docs.stripe.com/payments/checkout/customization.md) - [Personnaliser votre page de confirmation de paiement](https://docs.stripe.com/payments/checkout/custom-success-page.md)