feat: Create payment sessions (#6549)

~~Opening a draft PR to discuss a couple of implementation details that we should align on~~

**What**

Add workflow and API endpoint for creating payment sessions for a payment collection. Endpoint is currently `POST /store/payment-collection/:id/payment-sessions`. I suggested an alternative in a comment below.

Please note, we intentionally do not want to support creating payment sessions in bulk, as this would become a mess when having to manage multiple calls to third-party providers.
This commit is contained in:
Oli Juhl
2024-03-05 09:40:47 +01:00
committed by GitHub
parent 908b1dc3a2
commit 84208aafc1
30 changed files with 603 additions and 182 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
export * from "./cart"
export * from "./inventory"
export * from "./line-item"
export * from "./payment-collection"
export * from "./price-list"
export * from "./product"
@@ -0,0 +1,2 @@
export * from "./steps"
export * from "./workflows"
@@ -0,0 +1,46 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPaymentModuleService, PaymentProviderContext } from "@medusajs/types"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
interface StepInput {
payment_collection_id: string
provider_id: string
amount: number
currency_code: string
context?: PaymentProviderContext
data?: Record<string, unknown>
}
export const createPaymentSessionStepId = "create-payment-session"
export const createPaymentSessionStep = createStep(
createPaymentSessionStepId,
async (input: StepInput, { container }) => {
const service = container.resolve<IPaymentModuleService>(
ModuleRegistrationName.PAYMENT
)
const session = await service.createPaymentSession(
input.payment_collection_id,
{
provider_id: input.provider_id,
currency_code: input.currency_code,
amount: input.amount,
data: input.data ?? {},
context: input.context,
}
)
return new StepResponse(session, session.id)
},
async (createdSession, { container }) => {
if (!createdSession) {
return
}
const service = container.resolve<IPaymentModuleService>(
ModuleRegistrationName.PAYMENT
)
await service.deletePaymentSession(createdSession)
}
)
@@ -0,0 +1,3 @@
export * from "./create-payment-session"
export * from "./retrieve-payment-collection"
@@ -0,0 +1,27 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
FindConfig,
IPaymentModuleService,
PaymentCollectionDTO,
} from "@medusajs/types"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
interface StepInput {
id: string
config?: FindConfig<PaymentCollectionDTO>
}
export const retrievePaymentCollectionStepId = "retrieve-payment-collection"
export const retrievePaymentCollectionStep = createStep(
retrievePaymentCollectionStepId,
async (data: StepInput, { container }) => {
const paymentModuleService = container.resolve<IPaymentModuleService>(
ModuleRegistrationName.PAYMENT
)
const paymentCollection =
await paymentModuleService.retrievePaymentCollection(data.id, data.config)
return new StepResponse(paymentCollection)
}
)
@@ -0,0 +1,47 @@
import { PaymentProviderContext, PaymentSessionDTO } from "@medusajs/types"
import {
WorkflowData,
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import {
createPaymentSessionStep,
retrievePaymentCollectionStep,
} from "../steps"
interface WorkflowInput {
payment_collection_id: string
provider_id: string
data?: Record<string, unknown>
context?: PaymentProviderContext
}
export const createPaymentSessionsWorkflowId = "create-payment-sessions"
export const createPaymentSessionsWorkflow = createWorkflow(
createPaymentSessionsWorkflowId,
(input: WorkflowData<WorkflowInput>): WorkflowData<PaymentSessionDTO> => {
const paymentCollection = retrievePaymentCollectionStep({
id: input.payment_collection_id,
config: {
select: ["id", "amount", "currency_code"],
},
})
const paymentSessionInput = transform(
{ paymentCollection, input },
(data) => {
return {
payment_collection_id: data.input.payment_collection_id,
provider_id: data.input.provider_id,
data: data.input.data,
context: data.input.context,
amount: data.paymentCollection.amount,
currency_code: data.paymentCollection.currency_code,
}
}
)
const created = createPaymentSessionStep(paymentSessionInput)
return created
}
)
@@ -0,0 +1 @@
export * from "./create-payment-session"