# Stripe App > [!CAUTION] > Stripe App is not a production-ready app, but an integration example. It is not feature complete and must be self-hosted. > [!TIP] > Questions or issues? Check our [discord](https://discord.gg/H52JTZAtSH) channel for help. ## Overview Stripe App is a payment integration app that allows merchants to accept online payments from customers using Stripe as their payment processor. Stripe is a popular global payment provider that offers a range of payment methods, including credit cards, bank transfers, and digital wallets. You can find an example of using the Stripe App at [https://github.com/saleor/example-nextjs-stripe/](https://github.com/saleor/example-nextjs-stripe/). > [!IMPORTANT] > To configure the Stripe App, you must have an account with [Stripe](https://stripe.com). The Stripe App allows for integrations with [Stripe Payment Element](https://stripe.com/docs/payments/payment-element), meaning it can be used on [Web, iOS, Android, and React Native](https://stripe.com/docs/payments/accept-a-payment?platform=web). Under the hood, it creates Stripe [Payment Intents](https://stripe.com/docs/api/payment_intents) and handles calculations of total and balance in Saleor automatically. > [!NOTE] > Stripe App uses Stripe API version [2022-11-15](https://stripe.com/docs/api/versioning). ## Capabilities The Stripe App implements the following [Saleor synchronous events related to transactions](https://docs.saleor.io/docs/3.x/developer/extending/webhooks/synchronous-events/transaction): - [`PAYMENT_GATEWAY_INITIALIZE_SESSION`](https://docs.saleor.io/docs/3.x/api-reference/webhooks/enums/webhook-event-type-sync-enum#webhookeventtypesyncenumpayment_gateway_initialize_session) - [`TRANSACTION_INITIALIZE_SESSION`](https://docs.saleor.io/docs/3.x/api-reference/webhooks/enums/webhook-event-type-sync-enum#webhookeventtypesyncenumtransaction_initialize_session) - [`TRANSACTION_PROCESS_SESSION`](https://docs.saleor.io/docs/3.x/api-reference/webhooks/enums/webhook-event-type-sync-enum#webhookeventtypesyncenumtransaction_process_session) - [`TRANSACTION_CHARGE_REQUESTED`](https://docs.saleor.io/docs/3.x/api-reference/webhooks/enums/webhook-event-type-sync-enum#webhookeventtypesyncenumtransaction_charge_requested) - [`TRANSACTION_CANCEL_REQUESTED`](https://docs.saleor.io/docs/3.x/api-reference/webhooks/enums/webhook-event-type-sync-enum#webhookeventtypesyncenumtransaction_cancel_requested) - [`TRANSACTION_REFUND_REQUESTED`](https://docs.saleor.io/docs/3.x/api-reference/webhooks/enums/webhook-event-type-sync-enum#webhookeventtypesyncenumtransaction_refund_requested) Furthermore, it's also prepared to handle [Stripe incoming webhooks](https://stripe.com/docs/webhooks). Stripe App follows the flow described in detail in the [Saleor Payment App documentation](https://docs.saleor.io/docs/3.x/developer/payments#payment-app). ## Configuration For Stripe to appear as [available payment gateway](https://docs.saleor.io/docs/3.x/developer/checkout/finalizing#listing-available-payment-gateways), you need to [install it in the Saleor Dashboard](https://docs.saleor.io/docs/3.x/developer/app-store/overview#usage). You must obtain the Secret Key and Publishable Key from Stripe and paste it into the Stripe App configuration form. Webhooks to receive notifications from Stripe will be configured automatically. > [!CAUTION] > Stripe App doesn't work with Restricted Keys. ## Usage in Storefront or mobile apps Stripe App can be used to integrate with Stripe APIs. By using a set of GraphQL mutations, one can interact with Stripe to authorize, capture, refund, and cancel payments. ### Getting payment gateways The first step is to fetch the Checkout object including [`availablePaymentGateways`](https://docs.saleor.io/docs/3.x/api-reference/checkout/objects/checkout#checkoutavailablepaymentgatewayspaymentgateway--) field. The `availablePaymentGateways` field contains a list of payment gateways available for given checkout. The Stripe App should be one of the payment gateways available in the list. Its `id` is [`app.saleor.stripe`](https://stripe.saleor.app/api/manifest) - defined in app's manifest. ```graphql query { checkout(id: "Q2hlY2tvdXQ6YWY3MDJkMGQtMzM0NC00NjMxLTlkNmEtMDk4Yzk1ODhlNmMy") { availablePaymentGateways { id name } } } ``` The response: ```json { "data": { "checkout": { "availablePaymentGateways": [ { "id": "app.saleor.stripe", "name": "Stripe" } ] } } } ``` > [!NOTE] > The `availablePaymentGateways` may contain other Payment Apps as well as [legacy plugins](https://docs.saleor.io/docs/3.x/developer/extending/payment-gateways) configured in the Dashboard. You should ignore the ones that you don't want to use for a specific checkout. ### Paying with Stripe Payment Element To initialize the Stripe Payment Element, one needs to create a transaction in Saleor by calling the [`transactionInitialize`](https://docs.saleor.io/docs/3.x/api-reference/payments/mutations/transaction-initialize) mutation. ```graphql mutation StripeTransactionInitialize($data: JSON!) { transactionInitialize( id: "Q2hlY2tvdXQ6YWY3MDJkMGQtMzM0NC00NjMxLTlkNmEtMDk4Yzk1ODhlNmMy" amount: 54.24 paymentGateway: { id: "app.saleor.stripe", data: $data } ) { transactionEvent { pspReference amount { amount currency } type } data errors { field message code } } } ``` Where `$data` is an object passed to Stripe API to create a Payment Intent, for example: ```json { "automatic_payment_methods": { "enabled": true } } ``` The mutation returns the `TransactionInitialize` response: ```json { "data": { "transactionInitialize": { "transactionEvent": { "pspReference": "XXXX9XXXXXXXXX99", "amount": { "amount": 54.24, "currency": "EUR" }, "type": "CHARGE_REQUESTED" }, "data": { "paymentIntent": { "client_secret": "…" }, "publishableKey": "…" }, "errors": [] } } } ``` `client_secret` and `publishableKey` can be used to initialize the Stripe Payment Element. You can find a working example in this repository: [saleor/example-nextjs-stripe](https://github.com/saleor/example-nextjs-stripe/) ### Modifying the payment intent You can use the [`transactionProcess`](https://docs.saleor.io/docs/3.x/api-reference/payments/mutations/transaction-process) mutation to modify the payment intent. For example: ```graphql mutation StripeTransactionProcess($data: JSON!) { transactionProcess( id: "Q2hlY2tvdXQ6YWY3MDJkMGQtMzM0NC00NjMxLTlkNmEtMDk4Yzk1ODhlNmMy" data: $data ) { transactionEvent { pspReference amount { amount currency } type } data errors { field message code } } } ``` Where `$data` is an object passed to Stripe API to edit a Payment Intent, for example: ```json { "automatic_payment_methods": { "enabled": true } } ``` ### Retrieving publishable key In some cases, you might want to retrieve just the publishable key without creating any transactions in Saleor. This is particularly useful on a payment summary page where you want to display the details of Stripe Payment Intent. To do so, [`paymentGatewayInitialize`](https://docs.saleor.io/docs/3.x/api-reference/payments/mutations/payment-gateway-initialize) mutation can be used: ```graphql mutation PaymentGatewayInitialize($checkoutId: ID!) { paymentGatewayInitialize( id: $checkoutId amount: 0 paymentGateways: [{ id: "app.saleor.stripe" }] ) { gatewayConfigs { id data errors { field message code } } errors { field message code } } } ``` The response: ```json { "data": { "paymentGatewayInitialize": { "gatewayConfigs": [ { "id": "app.saleor.stripe", "data": { "publishableKey": "pk_test_…" }, "errors": [] } ], "errors": [] } } } ``` You can find an example of using the Stripe App at [https://github.com/saleor/example-nextjs-stripe/](https://github.com/saleor/example-nextjs-stripe/). ## Development To run the Stripe App locally: 1. Go to the app directory. 2. Copy the `.env.example` file to `.env`.The `.env` should contain the following variables: > [!NOTE] > Stripe App is a Next.js application. If you want to learn more about setting environment variables in Next.js, head over to the [documentation](https://nextjs.org/docs/basic-features/environment-variables). `SECRET_KEY` (_required_) A randomly generated key that encrypts metadata stored in Saleor. At least eight characters long. `APL` (_optional_) Name of the chosen implementation of the [Authentication Persistence Layer](https://github.com/saleor/saleor-app-sdk/blob/main/docs/apl.md). When no value is provided, `FileAPL` is used by default. See `saleor-app.ts` in the app directory to see supported APLs. `APP_DEBUG` (_optional_) The logging level for the app. The possible values are: `trace`, `debug`, `info`, `warn`, `error`, `fatal`, and `silent`. The default value is `info` which means that some information will be logged into the console. You can read more about our logger in [its documentation](https://getpino.io/#/docs/api?id=loggerlevel-string-gettersetter). ### Running app in development mode To run the app in development mode, run the following command: ```bash pnpm i pnpm dev ``` > [!NOTE] > pnpm 8.0.0 or higher is required to run the app. The app will be available at `http://localhost:3000`. > [!NOTE] > To test Stripe Webhooks, you need to expose your local server to the internet (tunnel). You can use Saleor CLI or Stripe CLI to do that. See [this guide](https://docs.saleor.io/docs/3.x/developer/extending/apps/developing-with-tunnels) for more details. ### Running tests To run tests, one needs to provide additional environment variables. Copy the `.env.test` file to `.env.test.local`.The `.env.test.local` should contain the following variables: | env variable name | required? | description | example | | ---------------------------------- | :--------: | :------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | | `TEST_SALEOR_API_URL` | _required_ | Full URL to the Saleor GraphQL endpoint | `https://saleor.cloud/graphql/` | | `TEST_SALEOR_APP_TOKEN` | _required_ | [AppToken](https://docs.saleor.io/docs/3.x/api-reference/apps/objects/app-token) | `3DZ7CbFTyPETthDixPtFpPysoKG4FP` | | `TEST_SALEOR_APP_ID` | _required_ | [App.id](https://docs.saleor.io/docs/3.x/api-reference/apps/objects/app) | `QXBwOjk=` | | `TEST_SALEOR_JWKS` | _required_ | stringified JWKS | `"{\"keys\": [{\"kty\": \"RSA\", \"key_ops\": [\"verify\"], \"n\": \"...\", \"e\": \"AQAB\", \"use\": \"sig\", \"kid\": \"1\"}]}"` | | `TEST_PAYMENT_APP_SECRET_KEY` | _required_ | Secret Key from Stripe | `sk_test_51LVZwxEosE…` | | `TEST_PAYMENT_APP_PUBLISHABLE_KEY` | _required_ | Publishable Key from Stripe | `pk_test_51LVZwxEos…` | | `TEST_PAYMENT_APP_WEBHOOK_ID` | _required_ | ID of a webhook | `we_1JaGFlH1Vac4G4dbZnQ8bviV` | | `TEST_PAYMENT_APP_WEBHOOK_SECRET` | _required_ | Webhook Secret from Stripe | `whsec_c09e3d87…` | Then run the following command: ```bash pnpm test ```