docs: improve payment related guides (#12502)

* improve guide

* update guides

* small change
This commit is contained in:
Shahed Nasser
2025-05-15 18:40:21 +03:00
committed by GitHub
parent b312a7e077
commit 22cdcedddc
26 changed files with 15844 additions and 15704 deletions
@@ -0,0 +1,44 @@
export const metadata = {
title: `Payment Steps in Checkout Flow`,
}
# {metadata.title}
In this guide, you'll learn about Medusa's accept payment flow that's used in checkout.
## Overview of the Payment Flow in Checkout
The Medusa application has a built-in payment flow that allows you to accept payments from customers, typically during checkout.
This flow is designed to be flexible and extensible, allowing you to integrate with various payment providers.
The payment flow consists of the following steps:
![A diagram showcasing the payment flow's steps](https://res.cloudinary.com/dza7lstvk/image/upload/v1711566781/Medusa%20Resources/payment-flow_jblrvw.jpg)
- [Create Payment Collection](!api!/store#payment-collections_postpaymentcollections): Create a payment collection associated with a cart.
- This payment collection will hold all details related to the payment operations.
- [Show Payment Providers](!api!/store#payment-providers_getpaymentproviders): Show the customer the available payment providers to choose from.
- You can integrate any [payment provider](../payment-provider/page.mdx), and you can enable them per region.
- [Create and Initialize Payment Session](!api!/store#payment-collections_postpaymentcollectionsidpaymentsessions): Create a payment session for the selected payment provider in the Medusa application, and initialize the session in the third-party payment provider.
- [Complete Cart](!api!/store#carts_postcartsidcomplete): Once the customer places the order, complete the cart, which involves:
- Authorizing the payment session with the third-party payment provider.
- If the third-party payment provider requires performing additional actions, show them to the customer, then retry cart completion.
---
## Implement Payment Checkout Step in Storefront
If you're using the [Next.js Starter Storefront](../../../nextjs-starter/page.mdx), the checkout flow is already implemented with the payment step.
If you're building a custom storefront, or you want to customize the checkout flow, you can follow the [Checkout in Storefront](../../../storefront-development/checkout/page.mdx) guide to learn how to build the checkout flow in the storefront, including the payment step.
---
{/* TODO add section on customizng the payment flow */}
## Build a Custom Payment Flow
You can also build a custom payment flow using workflows or the Payment Module's main service.
Refer to the [Accept Payment Flow](../payment-flow/page.mdx) guide to learn more.
@@ -1,18 +1,26 @@
import { CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: `Accept Payment Flow`,
title: `Accept Payment in Checkout Flow`,
}
# {metadata.title}
In this document, youll learn how to implement an accept-payment flow using workflows or the Payment Module's main service.
In this guide, you'll learn how to implement it using workflows or the Payment Module.
<Note>
## Why Implement the Payment Flow?
It's highly recommended to use Medusa's workflows to implement this flow. Use the Payment Module's main service for more complex cases.
Medusa already provides a built-in payment flow that allows you to accept payments from customers, which you can learn about in the [Accept Payment Flow in Checkout](../payment-checkout-flow/page.mdx) guide.
</Note>
You may need to implement a custom payment flow if you have a different use case, or you're using the Payment Module separately from the Medusa application.
This guide will help you understand how to implement a payment flow using the Payment Module's main service or workflows.
You can also follow this guide to get a general understanding of how the payment flow works in the Medusa application.
---
## How to Implement the Accept Payment Flow?
<Note title="Tip">
@@ -20,16 +28,18 @@ For a guide on how to implement this flow in the storefront, check out [this gui
</Note>
## Flow Overview
<Note>
![A diagram showcasing the payment flow's steps](https://res.cloudinary.com/dza7lstvk/image/upload/v1711566781/Medusa%20Resources/payment-flow_jblrvw.jpg)
It's highly recommended to use Medusa's workflows to implement this flow. Use the Payment Module's main service for more complex cases.
---
</Note>
## 1. Create a Payment Collection
### 1. Create a Payment Collection
A payment collection holds all details related to a resources payment operations. So, you start off by creating a payment collection.
In the Medusa application, you associate the payment collection with a cart, which is the resource that the customer is trying to pay for.
For example:
<CodeTabs group="workflow-service">
@@ -40,7 +50,7 @@ import { createPaymentCollectionForCartWorkflow } from "@medusajs/medusa/core-fl
// ...
await createPaymentCollectionForCartWorkflow(req.scope)
await createPaymentCollectionForCartWorkflow(container)
.run({
input: {
cart_id: "cart_123",
@@ -62,13 +72,50 @@ const paymentCollection =
</CodeTab>
</CodeTabs>
---
### 2. Show Payment Providers
## 2. Create Payment Sessions
Next, you'll show the customer the available payment providers to choose from.
In the Medusa application, you need to use [Query](!docs!/learn/fundamentals/module-links/query) to retrieve the available payment providers in a region.
<CodeTabs group="query-service">
<CodeTab label="Using Query" value="query">
```ts
const query = container.resolve("query")
const { data: regionPaymentProviders } = await query.graph({
entryPoint: "region_payment_provider",
variables: {
filters: {
region_id: "reg_123",
},
},
fields: ["payment_providers.*"],
})
const paymentProviders = regionPaymentProviders.map(
(relation) => relation.payment_providers
)
```
</CodeTab>
<CodeTab label="Using Service" value="service">
```ts
const paymentProviders = await paymentModuleService.listPaymentProviders()
```
</CodeTab>
</CodeTabs>
### 3. Create Payment Sessions
The payment collection has one or more payment sessions, each being a payment amount to be authorized by a payment provider.
So, after creating the payment collection, create at least one payment session for a provider.
So, once the customer selects a payment provider, create a payment session for the selected payment provider.
This will also initialize the payment session in the third-party payment provider.
For example:
@@ -80,11 +127,11 @@ import { createPaymentSessionsWorkflow } from "@medusajs/medusa/core-flows"
// ...
const { result: paymentSesion } = await createPaymentSessionsWorkflow(req.scope)
const { result: paymentSesion } = await createPaymentSessionsWorkflow(container)
.run({
input: {
payment_collection_id: "paycol_123",
provider_id: "stripe",
provider_id: "pp_stripe_stripe",
},
})
```
@@ -97,7 +144,7 @@ const paymentSession =
await paymentModuleService.createPaymentSession(
paymentCollection.id,
{
provider_id: "stripe",
provider_id: "pp_stripe_stripe",
currency_code: "usd",
amount: 5000,
data: {
@@ -111,11 +158,9 @@ const paymentSession =
</CodeTab>
</CodeTabs>
---
### 4. Authorize Payment Session
## 3. Authorize Payment Session
Once the customer chooses a payment session, start the authorization process. This may involve some action performed by the third-party payment provider, such as entering a 3DS code.
Once the customer places the order, you need to authorize the payment session with the third-party payment provider.
For example:
@@ -148,7 +193,7 @@ const payment = authorizePaymentSessionStep({
When the payment authorization is successful, a payment is created and returned.
### Handling Additional Action
#### Handling Additional Action
<Note>
@@ -184,14 +229,13 @@ try {
}
```
---
## 4. Payment Flow Complete
### 5. Payment Flow Complete
The payment flow is complete once the payment session is authorized and the payment is created.
You can then:
- Complete the cart using the [completeCartWorkflow](/references/medusa-workflows/completeCartWorkflow) if you're using the Medusa application.
- Capture the payment either using the [capturePaymentWorkflow](/references/medusa-workflows/capturePaymentWorkflow) or [capturePayment method](/references/payment/capturePayment).
- Refund captured amounts using the [refundPaymentWorkflow](/references/medusa-workflows/refundPaymentWorkflow) or [refundPayment method](/references/payment/refundPayment).
@@ -18,9 +18,23 @@ A payment collection can have multiple payment sessions. Using this feature, you
## data Property
Payment providers may need additional data to process the payment later. The `PaymentSession` data model has a `data` property used to store that data.
Payment providers may need additional data to process the payment later. For example, the ID of the session in the third-party provider.
For example, the customer's ID in Stripe is stored in the `data` property.
The `PaymentSession` data model has a `data` property used to store that data. It's set by the [payment provider in Medusa](../payment-provider/page.mdx) when the payment is initialized.
Then, when the payment session is authorized, the `data` property is used by the payment provider in Medusa to process the payment with the third-party provider.
<Note title="Tip">
If you're building a custom payment provider, learn more about initializing the payment session and setting the `data` property in the [Create Payment Provider](/references/payment/provider) guide.
</Note>
### data Property in the Storefront
This `data` property is accessible in the storefront as well. So, only store in it data that can be publicly shared, and data that is useful in the storefront.
For example, you can also store the client token used to initialize the payment session in the storefront with the third-party provider.
---
@@ -35,3 +35,19 @@ When a payment is refunded, a refund, represented by the [Refund data model](/re
A payment can be refunded multiple times, and each time a refund record is created.
![A diagram showcasing how a payment's multiple refunds are stored](https://res.cloudinary.com/dza7lstvk/image/upload/v1711565555/Medusa%20Resources/payment-refund_lgfvyy.jpg)
---
## data Property
Payment providers may need additional data to process the payment later. For example, the ID of the associated payment in the third-party provider.
The `Payment` data model has a `data` property used to store that data. The first time it's set is when the [payment provider in Medusa](../payment-provider/page.mdx) authorizes the payment.
Then, the `data` property is passed to the Medusa payment provider when the payment is captured or refunded, allowing the payment provider to utilize the data to process the payment with the third-party provider.
<Note title="Tip">
If you're building a custom payment provider, learn more about authorizing and capturing the payments and setting the `data` property in the [Create Payment Provider](/references/payment/provider) guide.
</Note>
@@ -1,38 +1,58 @@
export const metadata = {
title: `Webhook Events`,
title: `Payment Webhook Events`,
}
# {metadata.title}
In this document, youll learn how the Payment Module supports listening to webhook events.
In this guide, youll learn how you can handle payment webhook events in your Medusa application and using the Payment Module.
## What's a Webhook Event?
## What's a Payment Webhook Event?
A webhook event is sent from a third-party payment provider to your application. It indicates a change in a payments status.
A payment webhook event is a request sent from a third-party payment provider to your application. It indicates a change in a payments status.
This is useful in many cases such as when a payment is being processed asynchronously or when a request is interrupted and the payment provider is sending details on the process later.
This is useful in many cases such as:
- When a payment is processed (authorized or captured) asynchronously.
- When a payment is managed on the third-party payment provider's side.
- When a payment action on the frontend was interrupted, leading the payment to be processed without an order being created in the Medusa application.
So, it's essential to handle webhook events to ensure that your application is aware of updated payment statuses and can take appropriate actions.
---
## getWebhookActionAndData Method
## How to Handle Payment Webhook Events
The Payment Modules main service has a [getWebhookActionAndData method](/references/payment/getWebhookActionAndData) used to handle incoming webhook events from third-party payment services. The method delegates the handling to the associated payment provider, which returns the event's details.
### Webhook Listener API Route
Medusa implements a webhook listener route at the `/hooks/payment/[identifier]_[provider]` API route, where:
The Medusa application has a `/hooks/payment/[identifier]_[provider]` API route out-of-the-box that allows you to listen to webhook events from third-party payment providers, where:
- `[identifier]` is the `identifier` static property defined in the payment provider. For example, `stripe`.
- `[provider]` is the ID of the provider. For example, `stripe`.
For example, when integrating basic Stripe payments with the [Stripe Module Provider](../payment-provider/stripe/page.mdx), the webhook listener route is `/hooks/payment/stripe_stripe`. If you're integrating Stripe's Bancontact payments, the webhook listener route is `/hooks/payment/stripe-bancontact_stripe`.
For example, when integrating basic Stripe payments with the [Stripe Module Provider](../payment-provider/stripe/page.mdx), the webhook listener route is `/hooks/payment/stripe_stripe`.
Use that webhook listener in your third-party payment provider's configurations.
You can use this webhook listener when configuring webhook events in your third-party payment provider.
### getWebhookActionAndData Method
The webhook listener API route executes the [getWebhookActionAndData method](/references/payment/getWebhookActionAndData) of the Payment Module's main service. This method delegates handling of incoming webhook events to the relevant payment provider.
<Note title="Tip">
Payment providers have a similar [getWebhookActionAndData method](/references/payment/provider) to process the webhook event. So, if you're implementing a custom payment provider, make sure to implement it to handle webhook events.
</Note>
![A diagram showcasing the steps of how the getWebhookActionAndData method words](https://res.cloudinary.com/dza7lstvk/image/upload/v1711567415/Medusa%20Resources/payment-webhook_seaocg.jpg)
If the event's details indicate that the payment should be authorized, then the [authorizePaymentSession method of the main service](/references/payment/authorizePaymentSession) is executed on the specified payment session.
If the `getWebhookActionAndData` method returns an `authorized` or `captured` action, the Medusa application will perform one of the following actions:
If the event's details indicate that the payment should be captured, then the [capturePayment method of the main service](/references/payment/capturePayment) is executed on the payment of the specified payment session.
<Note>
### Actions After Webhook Payment Processing
View the full flow of the webhook event processing in the [processPaymentWorkflow](/references/medusa-workflows/processPaymentWorkflow) reference.
After the payment webhook actions are processed and the payment is authorized or captured, the Medusa application completes the cart associated with the payment's collection if it's not completed yet.
</Note>
- If the method returns an `authorized` action, Medusa will set the associated payment session to `authorized`.
- If the method returns a `captured` action, Medusa will set the associated payment session to `captured`.
- In either cases, if the cart associated with the payment session is not completed yet, Medusa will complete the cart.