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:
@@ -0,0 +1,142 @@
|
||||
import {
|
||||
createPaymentSessionsWorkflow,
|
||||
createPaymentSessionsWorkflowId,
|
||||
} from "@medusajs/core-flows"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPaymentModuleService, IRegionModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
|
||||
describe("Carts workflows", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let paymentModule: IPaymentModuleService
|
||||
let regionModule: IRegionModuleService
|
||||
let remoteLink
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT)
|
||||
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||
remoteLink = appContainer.resolve("remoteLink")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
describe("createPaymentSessionWorkflow", () => {
|
||||
it("should create payment sessions", async () => {
|
||||
const region = await regionModule.create({
|
||||
currency_code: "usd",
|
||||
name: "US",
|
||||
})
|
||||
|
||||
let paymentCollection = await paymentModule.createPaymentCollections({
|
||||
currency_code: "usd",
|
||||
amount: 1000,
|
||||
region_id: region.id,
|
||||
})
|
||||
|
||||
await createPaymentSessionsWorkflow(appContainer).run({
|
||||
input: {
|
||||
payment_collection_id: paymentCollection.id,
|
||||
provider_id: "pp_system_default",
|
||||
context: {},
|
||||
data: {},
|
||||
},
|
||||
})
|
||||
|
||||
paymentCollection = await paymentModule.retrievePaymentCollection(
|
||||
paymentCollection.id,
|
||||
{
|
||||
relations: ["payment_sessions"],
|
||||
}
|
||||
)
|
||||
|
||||
expect(paymentCollection).toEqual(
|
||||
expect.objectContaining({
|
||||
id: paymentCollection.id,
|
||||
currency_code: "usd",
|
||||
amount: 1000,
|
||||
region_id: region.id,
|
||||
payment_sessions: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 1000,
|
||||
currency_code: "usd",
|
||||
provider_id: "pp_system_default",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
describe("compensation", () => {
|
||||
it("should delete created payment collection if a subsequent step fails", async () => {
|
||||
const workflow = createPaymentSessionsWorkflow(appContainer)
|
||||
|
||||
workflow.appendAction("throw", createPaymentSessionsWorkflowId, {
|
||||
invoke: async function failStep() {
|
||||
throw new Error(
|
||||
`Failed to do something after creating payment sessions`
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
const region = await regionModule.create({
|
||||
currency_code: "usd",
|
||||
name: "US",
|
||||
})
|
||||
|
||||
let paymentCollection = await paymentModule.createPaymentCollections({
|
||||
currency_code: "usd",
|
||||
amount: 1000,
|
||||
region_id: region.id,
|
||||
})
|
||||
|
||||
const { errors } = await workflow.run({
|
||||
input: {
|
||||
payment_collection_id: paymentCollection.id,
|
||||
provider_id: "pp_system_default",
|
||||
context: {},
|
||||
data: {},
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "throw",
|
||||
handlerType: "invoke",
|
||||
error: new Error(
|
||||
`Failed to do something after creating payment sessions`
|
||||
),
|
||||
},
|
||||
])
|
||||
|
||||
const sessions = await paymentModule.listPaymentSessions({
|
||||
payment_collection_id: paymentCollection.id,
|
||||
})
|
||||
|
||||
expect(sessions).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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"
|
||||
@@ -1,22 +1,19 @@
|
||||
import { createCartWorkflow } from "@medusajs/core-flows"
|
||||
import { CreateCartWorkflowInputDTO } from "@medusajs/types"
|
||||
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../types/routing"
|
||||
|
||||
import { createCartWorkflow } from "@medusajs/core-flows"
|
||||
import { CreateCartWorkflowInputDTO } from "@medusajs/types"
|
||||
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
||||
import { defaultStoreCartFields } from "../carts/query-config"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<CreateCartWorkflowInputDTO>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const workflowInput = req.validatedBody
|
||||
|
||||
// If the customer is logged in, we auto-assign them to the cart
|
||||
if (req.auth?.actor_id) {
|
||||
workflowInput.customer_id = req.auth.actor_id
|
||||
const workflowInput = {
|
||||
...req.validatedBody,
|
||||
customer_id: req.auth?.actor_id,
|
||||
}
|
||||
|
||||
const { result, errors } = await createCartWorkflow(req.scope).run({
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { transformBody } from "../../../../../api/middlewares"
|
||||
import { MiddlewareRoute } from "../../../../../loaders/helpers/routing/types"
|
||||
import { StorePostPaymentCollectionsPaymentSessionReq } from "./validators"
|
||||
|
||||
export const storeCartRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/store/payment-collections/:id/payment-sessions",
|
||||
middlewares: [transformBody(StorePostPaymentCollectionsPaymentSessionReq)],
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
export const defaultStorePaymentCollectionFields = [
|
||||
"id",
|
||||
"currency_code",
|
||||
"amount",
|
||||
"payment_sessions",
|
||||
"payment_sessions.id",
|
||||
"payment_sessions.amount",
|
||||
"payment_sessions.provider_id",
|
||||
]
|
||||
|
||||
export const defaultStorePaymentCollectionRelations = ["payment_sessions"]
|
||||
|
||||
export const allowedStorePaymentCollectionRelations = ["payment_sessions"]
|
||||
|
||||
export const retrieveTransformQueryConfig = {
|
||||
defaultFields: defaultStorePaymentCollectionFields,
|
||||
defaultRelations: defaultStorePaymentCollectionRelations,
|
||||
allowedRelations: allowedStorePaymentCollectionRelations,
|
||||
isList: false,
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createPaymentSessionsWorkflow } from "@medusajs/core-flows"
|
||||
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../types/routing"
|
||||
import { defaultStorePaymentCollectionFields } from "./query-config"
|
||||
import { StorePostPaymentCollectionsPaymentSessionReq } from "./validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<StorePostPaymentCollectionsPaymentSessionReq>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { id } = req.params
|
||||
const { context, provider_id, data } = req.body
|
||||
|
||||
// If the customer is logged in, we auto-assign them to the payment collection
|
||||
if (req.auth?.actor_id) {
|
||||
context.customer = {
|
||||
...context.customer,
|
||||
id: req.auth.actor_id,
|
||||
}
|
||||
}
|
||||
|
||||
const workflowInput = {
|
||||
payment_collection_id: id,
|
||||
provider_id: provider_id,
|
||||
data,
|
||||
context,
|
||||
}
|
||||
|
||||
const { errors } = await createPaymentSessionsWorkflow(req.scope).run({
|
||||
input: workflowInput as any,
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const remoteQuery = req.scope.resolve("remoteQuery")
|
||||
|
||||
const query = remoteQueryObjectFromString({
|
||||
entryPoint: "payment_collection",
|
||||
variables: { cart: { id } },
|
||||
fields: defaultStorePaymentCollectionFields,
|
||||
})
|
||||
|
||||
const [result] = await remoteQuery(query)
|
||||
|
||||
res.status(200).json({ payment_collection: result })
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { PaymentProviderContext } from "@medusajs/types"
|
||||
|
||||
export class StorePostPaymentCollectionsPaymentSessionReq {
|
||||
provider_id: string
|
||||
context?: PaymentProviderContext
|
||||
data?: Record<string, unknown>
|
||||
}
|
||||
@@ -4,21 +4,22 @@ import Stripe from "stripe"
|
||||
|
||||
import {
|
||||
MedusaContainer,
|
||||
PaymentSessionStatus,
|
||||
PaymentProviderContext,
|
||||
PaymentProviderError,
|
||||
PaymentProviderSessionResponse,
|
||||
PaymentSessionStatus,
|
||||
ProviderWebhookPayload,
|
||||
UpdatePaymentProviderSession,
|
||||
WebhookActionResult,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
PaymentActions,
|
||||
AbstractPaymentProvider,
|
||||
isPaymentProviderError,
|
||||
MedusaError,
|
||||
PaymentActions,
|
||||
isPaymentProviderError,
|
||||
} from "@medusajs/utils"
|
||||
import { isDefined } from "medusa-core-utils"
|
||||
|
||||
import { CreatePaymentProviderSession } from "@medusajs/types"
|
||||
import {
|
||||
ErrorCodes,
|
||||
ErrorIntentStatus,
|
||||
@@ -103,26 +104,20 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeCredentials> {
|
||||
}
|
||||
|
||||
async initiatePayment(
|
||||
context: PaymentProviderContext
|
||||
input: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse> {
|
||||
const intentRequestData = this.getPaymentIntentOptions()
|
||||
const {
|
||||
email,
|
||||
context: cart_context,
|
||||
currency_code,
|
||||
amount,
|
||||
resource_id,
|
||||
customer,
|
||||
} = context
|
||||
const { email, extra, resource_id, customer } = input.context
|
||||
const { currency_code, amount } = input
|
||||
|
||||
const description = (cart_context.payment_description ??
|
||||
const description = (extra?.payment_description ??
|
||||
this.options_?.payment_description) as string
|
||||
|
||||
const intentRequest: Stripe.PaymentIntentCreateParams = {
|
||||
description,
|
||||
amount: Math.round(amount),
|
||||
currency: currency_code,
|
||||
metadata: { resource_id },
|
||||
metadata: { resource_id: resource_id ?? "Medusa Payment" },
|
||||
capture_method: this.options_.capture ? "automatic" : "manual",
|
||||
...intentRequestData,
|
||||
}
|
||||
@@ -149,9 +144,9 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeCredentials> {
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
|
||||
let session_data
|
||||
let sessionData
|
||||
try {
|
||||
session_data = (await this.stripe_.paymentIntents.create(
|
||||
sessionData = (await this.stripe_.paymentIntents.create(
|
||||
intentRequest
|
||||
)) as unknown as Record<string, unknown>
|
||||
} catch (e) {
|
||||
@@ -162,7 +157,7 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeCredentials> {
|
||||
}
|
||||
|
||||
return {
|
||||
data: session_data,
|
||||
data: sessionData,
|
||||
// TODO: REVISIT
|
||||
// update_requests: customer?.metadata?.stripe_id
|
||||
// ? undefined
|
||||
@@ -260,13 +255,14 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeCredentials> {
|
||||
}
|
||||
|
||||
async updatePayment(
|
||||
context: PaymentProviderContext
|
||||
input: UpdatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse> {
|
||||
const { amount, customer, payment_session_data } = context
|
||||
const stripeId = customer?.metadata?.stripe_id
|
||||
const { context, data, amount } = input
|
||||
|
||||
if (stripeId !== payment_session_data.customer) {
|
||||
const result = await this.initiatePayment(context)
|
||||
const stripeId = context.customer?.metadata?.stripe_id
|
||||
|
||||
if (stripeId !== data.customer) {
|
||||
const result = await this.initiatePayment(input)
|
||||
if (isPaymentProviderError(result)) {
|
||||
return this.buildError(
|
||||
"An error occurred in updatePayment during the initiate of the new payment for the new customer",
|
||||
@@ -276,12 +272,12 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeCredentials> {
|
||||
|
||||
return result
|
||||
} else {
|
||||
if (amount && payment_session_data.amount === Math.round(amount)) {
|
||||
return { data: payment_session_data }
|
||||
if (amount && data.amount === Math.round(amount)) {
|
||||
return { data }
|
||||
}
|
||||
|
||||
try {
|
||||
const id = payment_session_data.id as string
|
||||
const id = data.id as string
|
||||
const sessionData = (await this.stripe_.paymentIntents.update(id, {
|
||||
amount: Math.round(amount),
|
||||
})) as unknown as PaymentProviderSessionResponse["data"]
|
||||
|
||||
@@ -25,21 +25,21 @@ export const defaultPaymentSessionData = [
|
||||
amount: 100,
|
||||
currency_code: "usd",
|
||||
provider_id: "pp_system_default",
|
||||
payment_collection: "pay-col-id-1",
|
||||
payment_collection_id: "pay-col-id-1",
|
||||
},
|
||||
{
|
||||
id: "pay-sess-id-2",
|
||||
amount: 100,
|
||||
currency_code: "usd",
|
||||
provider_id: "pp_system_default",
|
||||
payment_collection: "pay-col-id-2",
|
||||
payment_collection_id: "pay-col-id-2",
|
||||
},
|
||||
{
|
||||
id: "pay-sess-id-3",
|
||||
amount: 100,
|
||||
currency_code: "usd",
|
||||
provider_id: "pp_system_default",
|
||||
payment_collection: "pay-col-id-2",
|
||||
payment_collection_id: "pay-col-id-2",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -48,7 +48,7 @@ export const defaultPaymentData = [
|
||||
id: "pay-id-1",
|
||||
amount: 100,
|
||||
currency_code: "usd",
|
||||
payment_collection: "pay-col-id-1",
|
||||
payment_collection_id: "pay-col-id-1",
|
||||
payment_session: "pay-sess-id-1",
|
||||
provider_id: "pp_system_default",
|
||||
authorized_amount: 100,
|
||||
@@ -59,7 +59,7 @@ export const defaultPaymentData = [
|
||||
amount: 100,
|
||||
authorized_amount: 100,
|
||||
currency_code: "usd",
|
||||
payment_collection: "pay-col-id-2",
|
||||
payment_collection_id: "pay-col-id-2",
|
||||
payment_session: "pay-sess-id-2",
|
||||
provider_id: "pp_system_default",
|
||||
data: {},
|
||||
|
||||
@@ -21,17 +21,9 @@ moduleIntegrationTestRunner({
|
||||
}: SuiteOptions<IPaymentModuleService>) => {
|
||||
describe("Payment Module Service", () => {
|
||||
describe("Payment Flow", () => {
|
||||
beforeEach(async () => {
|
||||
const repositoryManager = MikroOrmWrapper.forkManager()
|
||||
|
||||
await createPaymentCollections(repositoryManager)
|
||||
await createPaymentSessions(repositoryManager)
|
||||
await createPayments(repositoryManager)
|
||||
})
|
||||
|
||||
it("complete payment flow successfully", async () => {
|
||||
let paymentCollection = await service.createPaymentCollections({
|
||||
currency_code: "USD",
|
||||
currency_code: "usd",
|
||||
amount: 200,
|
||||
region_id: "reg_123",
|
||||
})
|
||||
@@ -40,11 +32,11 @@ moduleIntegrationTestRunner({
|
||||
paymentCollection.id,
|
||||
{
|
||||
provider_id: "pp_system_default",
|
||||
providerContext: {
|
||||
amount: 200,
|
||||
currency_code: "USD",
|
||||
payment_session_data: {},
|
||||
context: {},
|
||||
amount: 200,
|
||||
currency_code: "usd",
|
||||
data: {},
|
||||
context: {
|
||||
extra: {},
|
||||
customer: {},
|
||||
billing_address: {},
|
||||
email: "test@test.test.com",
|
||||
@@ -72,7 +64,7 @@ moduleIntegrationTestRunner({
|
||||
expect(paymentCollection).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
currency_code: "USD",
|
||||
currency_code: "usd",
|
||||
amount: 200,
|
||||
// TODO
|
||||
// authorized_amount: 200,
|
||||
@@ -83,7 +75,7 @@ moduleIntegrationTestRunner({
|
||||
payment_sessions: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
currency_code: "USD",
|
||||
currency_code: "usd",
|
||||
amount: 200,
|
||||
provider_id: "pp_system_default",
|
||||
status: "authorized",
|
||||
@@ -94,7 +86,7 @@ moduleIntegrationTestRunner({
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
amount: 200,
|
||||
currency_code: "USD",
|
||||
currency_code: "usd",
|
||||
provider_id: "pp_system_default",
|
||||
captures: [
|
||||
expect.objectContaining({
|
||||
@@ -336,11 +328,11 @@ moduleIntegrationTestRunner({
|
||||
it("should create a payment session successfully", async () => {
|
||||
await service.createPaymentSession("pay-col-id-1", {
|
||||
provider_id: "pp_system_default",
|
||||
providerContext: {
|
||||
amount: 200,
|
||||
currency_code: "usd",
|
||||
payment_session_data: {},
|
||||
context: {},
|
||||
amount: 200,
|
||||
currency_code: "usd",
|
||||
data: {},
|
||||
context: {
|
||||
extra: {},
|
||||
customer: {},
|
||||
billing_address: {},
|
||||
email: "test@test.test.com",
|
||||
@@ -377,11 +369,11 @@ moduleIntegrationTestRunner({
|
||||
it("should update a payment session successfully", async () => {
|
||||
let session = await service.createPaymentSession("pay-col-id-1", {
|
||||
provider_id: "pp_system_default",
|
||||
providerContext: {
|
||||
amount: 200,
|
||||
currency_code: "usd",
|
||||
payment_session_data: {},
|
||||
context: {},
|
||||
amount: 200,
|
||||
currency_code: "usd",
|
||||
data: {},
|
||||
context: {
|
||||
extra: {},
|
||||
customer: {},
|
||||
billing_address: {},
|
||||
email: "test@test.test.com",
|
||||
@@ -391,15 +383,15 @@ moduleIntegrationTestRunner({
|
||||
|
||||
session = await service.updatePaymentSession({
|
||||
id: session.id,
|
||||
providerContext: {
|
||||
amount: 200,
|
||||
currency_code: "eur",
|
||||
amount: 200,
|
||||
currency_code: "eur",
|
||||
data: {},
|
||||
context: {
|
||||
resource_id: "res_id",
|
||||
context: {},
|
||||
extra: {},
|
||||
customer: {},
|
||||
billing_address: {},
|
||||
email: "new@test.tsst",
|
||||
payment_session_data: {},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -424,11 +416,11 @@ moduleIntegrationTestRunner({
|
||||
|
||||
const session = await service.createPaymentSession(collection.id, {
|
||||
provider_id: "pp_system_default",
|
||||
providerContext: {
|
||||
amount: 100,
|
||||
currency_code: "usd",
|
||||
payment_session_data: {},
|
||||
context: {},
|
||||
amount: 100,
|
||||
currency_code: "usd",
|
||||
data: {},
|
||||
context: {
|
||||
extra: {},
|
||||
resource_id: "test",
|
||||
email: "test@test.com",
|
||||
billing_address: {},
|
||||
@@ -447,7 +439,6 @@ moduleIntegrationTestRunner({
|
||||
amount: 100,
|
||||
currency_code: "usd",
|
||||
provider_id: "pp_system_default",
|
||||
|
||||
refunds: [],
|
||||
captures: [],
|
||||
data: {},
|
||||
@@ -458,9 +449,7 @@ moduleIntegrationTestRunner({
|
||||
deleted_at: null,
|
||||
captured_at: null,
|
||||
canceled_at: null,
|
||||
payment_collection: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
payment_collection_id: expect.any(String),
|
||||
payment_session: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
updated_at: expect.any(Date),
|
||||
@@ -472,6 +461,10 @@ moduleIntegrationTestRunner({
|
||||
data: {},
|
||||
status: "authorized",
|
||||
authorized_at: expect.any(Date),
|
||||
payment_collection: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
payment_collection_id: expect.any(String),
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"@medusajs/modules-sdk": "^1.12.5",
|
||||
"@medusajs/types": "^1.11.9",
|
||||
"@medusajs/utils": "^1.11.2",
|
||||
"@medusajs/workflows-sdk": "workspace:^",
|
||||
"@mikro-orm/core": "5.9.7",
|
||||
"@mikro-orm/migrations": "5.9.7",
|
||||
"@mikro-orm/postgresql": "5.9.7",
|
||||
|
||||
@@ -22,6 +22,8 @@ export class Migration20240225134525 extends Migration {
|
||||
ALTER TABLE IF EXISTS "payment_provider" ADD COLUMN IF NOT EXISTS "is_enabled" BOOLEAN NOT NULL DEFAULT TRUE;
|
||||
|
||||
ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "payment_collection_id" TEXT NOT NULL;
|
||||
ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "currency_code" TEXT NOT NULL;
|
||||
ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "authorized_at" TEXT NULL;
|
||||
ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "payment_authorized_at" TIMESTAMPTZ NULL;
|
||||
ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL;
|
||||
ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL;
|
||||
@@ -31,6 +33,7 @@ export class Migration20240225134525 extends Migration {
|
||||
ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "provider_id" TEXT NOT NULL;
|
||||
ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL;
|
||||
ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL;
|
||||
ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "payment_session_id" TEXT NOT NULL;
|
||||
|
||||
ALTER TABLE IF EXISTS "refund" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL;
|
||||
ALTER TABLE IF EXISTS "refund" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL;
|
||||
@@ -176,7 +179,7 @@ export class Migration20240225134525 extends Migration {
|
||||
"captured_at" TIMESTAMPTZ NULL,
|
||||
"canceled_at" TIMESTAMPTZ NULL,
|
||||
"payment_collection_id" TEXT NOT NULL,
|
||||
"session_id" TEXT NOT NULL,
|
||||
"payment_session_id" TEXT NOT NULL,
|
||||
"metadata" JSONB NULL,
|
||||
CONSTRAINT "payment_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
@@ -84,12 +84,12 @@ export default class PaymentCollection {
|
||||
payment_providers = new Collection<PaymentProvider>(this)
|
||||
|
||||
@OneToMany(() => PaymentSession, (ps) => ps.payment_collection, {
|
||||
cascade: [Cascade.REMOVE],
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
})
|
||||
payment_sessions = new Collection<PaymentSession>(this)
|
||||
|
||||
@OneToMany(() => Payment, (payment) => payment.payment_collection, {
|
||||
cascade: [Cascade.REMOVE],
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
})
|
||||
payments = new Collection<Payment>(this)
|
||||
|
||||
|
||||
@@ -54,19 +54,24 @@ export default class PaymentSession {
|
||||
})
|
||||
authorized_at: Date | null = null
|
||||
|
||||
@ManyToOne(() => PaymentCollection, {
|
||||
persist: false,
|
||||
})
|
||||
payment_collection: PaymentCollection
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => PaymentCollection,
|
||||
columnType: "text",
|
||||
index: "IDX_payment_session_payment_collection_id",
|
||||
fieldName: "payment_collection_id",
|
||||
onDelete: "cascade",
|
||||
mapToPk: true,
|
||||
})
|
||||
payment_collection!: PaymentCollection
|
||||
payment_collection_id: string
|
||||
|
||||
@OneToOne({
|
||||
entity: () => Payment,
|
||||
mappedBy: (payment) => payment.payment_session,
|
||||
cascade: ["soft-remove"] as any,
|
||||
nullable: true,
|
||||
mappedBy: "payment_session",
|
||||
})
|
||||
payment?: Payment | null
|
||||
|
||||
|
||||
@@ -109,18 +109,26 @@ export default class Payment {
|
||||
captures = new Collection<Capture>(this)
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => PaymentCollection,
|
||||
persist: false,
|
||||
})
|
||||
payment_collection: PaymentCollection
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => PaymentCollection,
|
||||
columnType: "text",
|
||||
index: "IDX_payment_payment_collection_id",
|
||||
fieldName: "payment_collection_id",
|
||||
onDelete: "cascade",
|
||||
mapToPk: true,
|
||||
})
|
||||
payment_collection!: PaymentCollection
|
||||
payment_collection_id: string
|
||||
|
||||
@OneToOne({
|
||||
owner: true,
|
||||
fieldName: "session_id",
|
||||
fieldName: "payment_session_id",
|
||||
index: "IDX_payment_payment_session_id",
|
||||
})
|
||||
payment_session!: PaymentSession
|
||||
payment_session: PaymentSession
|
||||
|
||||
/** COMPUTED PROPERTIES START **/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
PaymentProviderContext,
|
||||
CreatePaymentProviderSession,
|
||||
PaymentProviderError,
|
||||
PaymentProviderSessionResponse,
|
||||
PaymentSessionStatus,
|
||||
@@ -21,7 +21,7 @@ export class SystemProviderService extends AbstractPaymentProvider {
|
||||
}
|
||||
|
||||
async initiatePayment(
|
||||
context: PaymentProviderContext
|
||||
context: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderSessionResponse> {
|
||||
return { data: {} }
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
UpdatePaymentSessionDTO,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
@@ -35,7 +36,6 @@ import {
|
||||
PaymentSession,
|
||||
Refund,
|
||||
} from "@models"
|
||||
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import PaymentProviderService from "./payment-provider"
|
||||
|
||||
@@ -49,7 +49,7 @@ type InjectedDependencies = {
|
||||
paymentProviderService: PaymentProviderService
|
||||
}
|
||||
|
||||
const generateMethodForModels = [PaymentCollection, Payment]
|
||||
const generateMethodForModels = [PaymentCollection, Payment, PaymentSession]
|
||||
|
||||
export default class PaymentModuleService<
|
||||
TPaymentCollection extends PaymentCollection = PaymentCollection,
|
||||
@@ -201,44 +201,67 @@ export default class PaymentModuleService<
|
||||
)
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@InjectManager("baseRepository_")
|
||||
async createPaymentSession(
|
||||
paymentCollectionId: string,
|
||||
input: CreatePaymentSessionDTO,
|
||||
@MedusaContext() sharedContext?: Context
|
||||
): Promise<PaymentSessionDTO> {
|
||||
let paymentSession: PaymentSession
|
||||
|
||||
try {
|
||||
const providerSessionSession =
|
||||
await this.paymentProviderService_.createSession(input.provider_id, {
|
||||
context: input.context ?? {},
|
||||
amount: input.amount,
|
||||
currency_code: input.currency_code,
|
||||
})
|
||||
|
||||
input.data = {
|
||||
...input.data,
|
||||
...providerSessionSession,
|
||||
}
|
||||
|
||||
paymentSession = await this.createPaymentSession_(
|
||||
paymentCollectionId,
|
||||
input,
|
||||
sharedContext
|
||||
)
|
||||
} catch (error) {
|
||||
// In case the session is created at the provider, but fails to be created in Medusa,
|
||||
// we catch the error and delete the session at the provider and rethrow.
|
||||
await this.paymentProviderService_.deleteSession({
|
||||
provider_id: input.provider_id,
|
||||
data: input.data,
|
||||
})
|
||||
|
||||
throw error
|
||||
}
|
||||
|
||||
return await this.baseRepository_.serialize(paymentSession, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async createPaymentSession_(
|
||||
paymentCollectionId: string,
|
||||
data: CreatePaymentSessionDTO,
|
||||
@MedusaContext() sharedContext?: Context
|
||||
): Promise<PaymentSessionDTO> {
|
||||
const created = await this.paymentSessionService_.create(
|
||||
): Promise<PaymentSession> {
|
||||
const paymentSession = await this.paymentSessionService_.create(
|
||||
{
|
||||
payment_collection_id: paymentCollectionId,
|
||||
provider_id: data.provider_id,
|
||||
amount: data.providerContext.amount,
|
||||
currency_code: data.providerContext.currency_code,
|
||||
payment_collection: paymentCollectionId,
|
||||
amount: data.amount,
|
||||
currency_code: data.currency_code,
|
||||
context: data.context,
|
||||
data: data.data,
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
try {
|
||||
const sessionData = await this.paymentProviderService_.createSession(
|
||||
data.provider_id,
|
||||
{
|
||||
...data.providerContext,
|
||||
resource_id: created.id,
|
||||
}
|
||||
)
|
||||
|
||||
await this.paymentSessionService_.update(
|
||||
{
|
||||
id: created.id,
|
||||
data: sessionData,
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize(created, { populate: true })
|
||||
} catch (e) {
|
||||
await this.paymentSessionService_.delete([created.id], sharedContext)
|
||||
throw e
|
||||
}
|
||||
return paymentSession
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -252,17 +275,12 @@ export default class PaymentModuleService<
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const sessionData = await this.paymentProviderService_.updateSession(
|
||||
session.provider_id,
|
||||
data.providerContext
|
||||
)
|
||||
|
||||
const updated = await this.paymentSessionService_.update(
|
||||
{
|
||||
id: session.id,
|
||||
amount: data.providerContext.amount,
|
||||
currency_code: data.providerContext.currency_code,
|
||||
data: sessionData,
|
||||
amount: data.amount,
|
||||
currency_code: data.currency_code,
|
||||
data: data.data,
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
@@ -298,8 +316,14 @@ export default class PaymentModuleService<
|
||||
const session = await this.paymentSessionService_.retrieve(
|
||||
id,
|
||||
{
|
||||
select: ["id", "data", "provider_id", "amount", "currency_code"],
|
||||
relations: ["payment_collection"],
|
||||
select: [
|
||||
"id",
|
||||
"data",
|
||||
"provider_id",
|
||||
"amount",
|
||||
"currency_code",
|
||||
"payment_collection_id",
|
||||
],
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
@@ -348,7 +372,7 @@ export default class PaymentModuleService<
|
||||
amount: session.amount,
|
||||
currency_code: session.currency_code,
|
||||
payment_session: session.id,
|
||||
payment_collection: session.payment_collection!.id,
|
||||
payment_collection_id: session.payment_collection_id,
|
||||
provider_id: session.provider_id,
|
||||
// customer_id: context.customer.id,
|
||||
data,
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import { EOL } from "os"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import {
|
||||
Context,
|
||||
CreatePaymentProviderDTO,
|
||||
CreatePaymentProviderSession,
|
||||
DAL,
|
||||
InternalModuleDeclaration,
|
||||
IPaymentProvider,
|
||||
PaymentProviderAuthorizeResponse,
|
||||
PaymentProviderContext,
|
||||
PaymentProviderDataInput,
|
||||
PaymentProviderError,
|
||||
PaymentProviderSessionResponse,
|
||||
PaymentSessionStatus,
|
||||
ProviderWebhookPayload,
|
||||
UpdatePaymentProviderSession,
|
||||
WebhookActionResult,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
@@ -21,8 +20,9 @@ import {
|
||||
isPaymentProviderError,
|
||||
MedusaContext,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { PaymentProvider } from "@models"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { EOL } from "os"
|
||||
|
||||
type InjectedDependencies = {
|
||||
paymentProviderRepository: DAL.RepositoryService
|
||||
@@ -70,20 +70,10 @@ export default class PaymentProviderService {
|
||||
|
||||
async createSession(
|
||||
providerId: string,
|
||||
sessionInput: PaymentProviderContext
|
||||
sessionInput: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderSessionResponse["data"]> {
|
||||
const provider = this.retrieveProvider(providerId)
|
||||
|
||||
if (
|
||||
!isDefined(sessionInput.currency_code) ||
|
||||
!isDefined(sessionInput.amount)
|
||||
) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_ARGUMENT,
|
||||
"`currency_code` and `amount` are required to create payment session."
|
||||
)
|
||||
}
|
||||
|
||||
const paymentResponse = await provider.initiatePayment(sessionInput)
|
||||
|
||||
if (isPaymentProviderError(paymentResponse)) {
|
||||
@@ -95,7 +85,7 @@ export default class PaymentProviderService {
|
||||
|
||||
async updateSession(
|
||||
providerId: string,
|
||||
sessionInput: PaymentProviderContext
|
||||
sessionInput: UpdatePaymentProviderSession
|
||||
): Promise<Record<string, unknown> | undefined> {
|
||||
const provider = this.retrieveProvider(providerId)
|
||||
|
||||
|
||||
@@ -169,6 +169,19 @@ export interface FilterablePaymentCollectionProps
|
||||
updated_at?: OperatorMap<string>
|
||||
}
|
||||
|
||||
export interface FilterablePaymentSessionProps
|
||||
extends BaseFilterable<PaymentSessionDTO> {
|
||||
id?: string | string[]
|
||||
currency_code?: string | string[]
|
||||
amount?: number | OperatorMap<number>
|
||||
provider_id?: string | string[]
|
||||
payment_collection_id?: string | string[]
|
||||
region_id?: string | string[] | OperatorMap<string>
|
||||
created_at?: OperatorMap<string>
|
||||
updated_at?: OperatorMap<string>
|
||||
deleted_at?: OperatorMap<string>
|
||||
}
|
||||
|
||||
/* ********** PAYMENT ********** */
|
||||
export interface PaymentDTO {
|
||||
/**
|
||||
|
||||
@@ -186,9 +186,21 @@ export interface CreatePaymentSessionDTO {
|
||||
*/
|
||||
provider_id: string
|
||||
/**
|
||||
* The provider's context.
|
||||
* The selected currency code.
|
||||
*/
|
||||
providerContext: Omit<PaymentProviderContext, "resource_id">
|
||||
currency_code: string
|
||||
/**
|
||||
* The payment's amount.
|
||||
*/
|
||||
amount: number
|
||||
/**
|
||||
* The value of the payment session's `data` field.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
/**
|
||||
* The payment session's context.
|
||||
*/
|
||||
context?: PaymentProviderContext
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,10 +211,22 @@ export interface UpdatePaymentSessionDTO {
|
||||
* The payment session's ID.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The value of the payment session's `data` field.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
/**
|
||||
* The selected currency code.
|
||||
*/
|
||||
currency_code: string
|
||||
/**
|
||||
* The payment's amount.
|
||||
*/
|
||||
amount: number
|
||||
/**
|
||||
* The payment session's context.
|
||||
*/
|
||||
providerContext: PaymentProviderContext
|
||||
context?: PaymentProviderContext
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PaymentSessionStatus } from "./common"
|
||||
import { CustomerDTO } from "../customer"
|
||||
import { AddressDTO } from "../address"
|
||||
import { CustomerDTO } from "../customer"
|
||||
import { PaymentSessionStatus } from "./common"
|
||||
import { ProviderWebhookPayload } from "./mutations"
|
||||
|
||||
export type PaymentAddressDTO = Partial<AddressDTO>
|
||||
@@ -43,31 +43,31 @@ export type PaymentProviderContext = {
|
||||
* The customer's email.
|
||||
*/
|
||||
email?: string
|
||||
/**
|
||||
* The selected currency code.
|
||||
*/
|
||||
currency_code: string
|
||||
/**
|
||||
* The payment's amount.
|
||||
*/
|
||||
amount: number
|
||||
/**
|
||||
* The ID of the resource the payment is associated with i.e. the ID of the PaymentSession in Medusa
|
||||
*/
|
||||
resource_id: string
|
||||
resource_id?: string
|
||||
/**
|
||||
* The customer associated with this payment.
|
||||
*/
|
||||
customer?: PaymentCustomerDTO
|
||||
/**
|
||||
* The context.
|
||||
* The extra fields specific to the provider session.
|
||||
*/
|
||||
context: { payment_description?: string } & Record<string, unknown>
|
||||
/**
|
||||
* If the payment session hasn't been created or initiated yet, it'll be an empty object.
|
||||
* If the payment session exists, it'll be the value of the payment session's `data` field.
|
||||
*/
|
||||
payment_session_data: Record<string, unknown>
|
||||
extra?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export type CreatePaymentProviderSession = {
|
||||
context: PaymentProviderContext
|
||||
amount: number
|
||||
currency_code: string
|
||||
}
|
||||
|
||||
export type UpdatePaymentProviderSession = {
|
||||
context: PaymentProviderContext
|
||||
data: Record<string, unknown>
|
||||
amount: number
|
||||
currency_code: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,21 +142,21 @@ export interface IPaymentProvider {
|
||||
/**
|
||||
* Make calls to the third-party provider to initialize the payment. For example, in Stripe this method is used to create a Payment Intent for the customer.
|
||||
*
|
||||
* @param {PaymentProviderContext} context - The context of the payment.
|
||||
* @param {CreatePaymentProviderSession} context
|
||||
* @returns {Promise<PaymentProviderError | PaymentProviderSessionResponse>} Either the payment's data or an error object.
|
||||
*/
|
||||
initiatePayment(
|
||||
context: PaymentProviderContext
|
||||
data: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
|
||||
/**
|
||||
* This method is used to update the payment session.
|
||||
*
|
||||
* @param {PaymentProviderContext} context - The context of the payment.
|
||||
* @param {UpdatePaymentProviderSession} context
|
||||
* @returns {Promise<PaymentProviderError | PaymentProviderSessionResponse | void>} Either the payment's data or an error object.
|
||||
*/
|
||||
updatePayment(
|
||||
context: PaymentProviderContext
|
||||
context: UpdatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Context } from "../shared-context"
|
||||
import {
|
||||
FilterablePaymentCollectionProps,
|
||||
FilterablePaymentProps,
|
||||
FilterablePaymentSessionProps,
|
||||
PaymentCollectionDTO,
|
||||
PaymentDTO,
|
||||
PaymentSessionDTO,
|
||||
@@ -387,6 +388,12 @@ export interface IPaymentModuleService extends IModuleService {
|
||||
*/
|
||||
cancelPayment(paymentId: string, sharedContext?: Context): Promise<PaymentDTO>
|
||||
|
||||
listPaymentSessions(
|
||||
filters?: FilterablePaymentSessionProps,
|
||||
config?: FindConfig<PaymentSessionDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<PaymentSessionDTO[]>
|
||||
|
||||
/**
|
||||
* This method creates providers on load.
|
||||
*
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import {
|
||||
CreatePaymentProviderSession,
|
||||
IPaymentProvider,
|
||||
MedusaContainer,
|
||||
PaymentProviderContext,
|
||||
PaymentProviderError,
|
||||
PaymentProviderSessionResponse,
|
||||
PaymentSessionStatus,
|
||||
ProviderWebhookPayload,
|
||||
WebhookActionResult,
|
||||
UpdatePaymentProviderSession,
|
||||
WebhookActionResult
|
||||
} from "@medusajs/types"
|
||||
|
||||
export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
@@ -107,7 +108,7 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
|
||||
abstract initiatePayment(
|
||||
context: PaymentProviderContext
|
||||
context: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
|
||||
abstract deletePayment(
|
||||
@@ -128,7 +129,7 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
|
||||
abstract updatePayment(
|
||||
context: PaymentProviderContext
|
||||
context: UpdatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
|
||||
abstract getWebhookActionAndData(
|
||||
|
||||
@@ -8642,6 +8642,7 @@ __metadata:
|
||||
"@medusajs/modules-sdk": ^1.12.5
|
||||
"@medusajs/types": ^1.11.9
|
||||
"@medusajs/utils": ^1.11.2
|
||||
"@medusajs/workflows-sdk": "workspace:^"
|
||||
"@mikro-orm/cli": 5.9.7
|
||||
"@mikro-orm/core": 5.9.7
|
||||
"@mikro-orm/migrations": 5.9.7
|
||||
@@ -9126,7 +9127,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@medusajs/workflows-sdk@^0.1.2, @medusajs/workflows-sdk@^0.1.3, @medusajs/workflows-sdk@workspace:packages/workflows-sdk":
|
||||
"@medusajs/workflows-sdk@^0.1.2, @medusajs/workflows-sdk@^0.1.3, @medusajs/workflows-sdk@workspace:^, @medusajs/workflows-sdk@workspace:packages/workflows-sdk":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@medusajs/workflows-sdk@workspace:packages/workflows-sdk"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user