Skip to content

Commit

Permalink
feat: add payment authorization workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
silenaker committed Sep 27, 2024
1 parent 91e9e3e commit 89ecdb4
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 125 deletions.
3 changes: 1 addition & 2 deletions packages/core/core-flows/src/cart/workflows/complete-cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
useRemoteQueryStep,
} from "../../common"
import { createOrdersStep } from "../../order/steps/create-orders"
import { authorizePaymentSessionStep } from "../../payment/steps/authorize-payment-session"
import { authorizePaymentSessionStep } from "../../payment-collection"
import { registerUsageStep } from "../../promotion/steps/register-usage"
import { updateCartsStep, validateCartPaymentsStep } from "../steps"
import { reserveInventoryStep } from "../steps/reserve-inventory"
Expand Down Expand Up @@ -58,7 +58,6 @@ export const completeCartWorkflow = createWorkflow(
// We choose the first payment session, as there will only be one active payment session
// This might change in the future.
id: paymentSessions[0].id,
context: { cart_id: cart.id },
})

const { variants, items, sales_channel_id } = transform(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import {
WorkflowResponse,
createStep,
createWorkflow,
when,
} from "@medusajs/workflows-sdk"
import { useRemoteQueryStep } from "../../common"
import { capturePaymentWorkflow } from "../../payment"
import {
authorizePaymentSessionStep,
capturePaymentWorkflow,
} from "../../payment"
import { createPaymentSessionsWorkflow } from "../../payment-collection"
createPaymentSessionsWorkflow,
} from "../../payment-collection"

/**
* This step validates that the payment collection is not_paid
Expand Down Expand Up @@ -63,15 +64,16 @@ export const markPaymentCollectionAsPaid = createWorkflow(

const payment = authorizePaymentSessionStep({
id: paymentSession.id,
context: { order_id: input.order_id },
})

capturePaymentWorkflow.runAsStep({
input: {
payment_id: payment.id,
captured_by: input.captured_by,
amount: paymentCollection.amount,
},
when({ payment }, ({ payment }) => !!payment).then(() => {
capturePaymentWorkflow.runAsStep({
input: {
payment_id: payment!.id,
captured_by: input.captured_by,
amount: paymentCollection.amount,
},
})
})

return new WorkflowResponse(payment)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { IPaymentModuleService, Logger } from "@medusajs/types"
import {
ContainerRegistrationKeys,
ModuleRegistrationName,
PaymentSessionStatus,
} from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"

export type AuthorizePaymentSessionStepInput = {
id: string
provider_token?: string
}

export const authorizePaymentSessionStepId = "authorize-payment-session-step"
/**
* This step authorizes a payment session.
*/
export const authorizePaymentSessionStep = createStep(
authorizePaymentSessionStepId,
async (input: AuthorizePaymentSessionStepInput, { container }) => {
const paymentModule = container.resolve<IPaymentModuleService>(
ModuleRegistrationName.PAYMENT
)
const payment = await paymentModule.authorizePaymentSession(input.id, {
provider_token: input.provider_token,
})
return new StepResponse(payment)
},
// If payment or any other part of complete cart fails post payment step, we cancel any payments made
async (payment, { container }) => {
if (!payment) {
return
}

const logger = container.resolve<Logger>(ContainerRegistrationKeys.LOGGER)
const paymentModule = container.resolve<IPaymentModuleService>(
ModuleRegistrationName.PAYMENT
)

try {
await paymentModule.cancelPayment(payment.id)
} catch (e) {
logger.error(
`Error was thrown trying to cancel payment - ${payment.id} - ${e}`
)
}
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from "./update-payment-collection"
export * from "./update-refund-reasons"
export * from "./validate-deleted-payment-sessions"
export * from "./cancel-payment-session"
export * from "./authorize-payment-session"
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {
WorkflowData,
WorkflowResponse,
createWorkflow,
} from "@medusajs/workflows-sdk"
import { authorizePaymentSessionStep } from "../steps"

export const authorizePaymentSessionWorkflowId =
"authorize-payment-session-workflow"

/**
* This workflow authorizes a payment session.
*/
export const authorizePaymentSessionWorkflow = createWorkflow(
authorizePaymentSessionWorkflowId,
(input: WorkflowData<{ id: string; provider_token?: string }>) => {
return new WorkflowResponse(authorizePaymentSessionStep(input))
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
WorkflowResponse,
createWorkflow,
} from "@medusajs/workflows-sdk"
import { cancelPaymentSessionStep } from "../steps/cancel-payment-session"
import { cancelPaymentSessionStep } from "../steps"

export const cancelPaymentSessionWorkflowId = "cancel-payment-session-workflow"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from "./create-refund-reasons"
export * from "./delete-payment-sessions"
export * from "./update-refund-reasons"
export * from "./cancel-payment-session"
export * from "./authorize-payment-session"

This file was deleted.

1 change: 0 additions & 1 deletion packages/core/core-flows/src/payment/steps/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from "./authorize-payment-session"
export * from "./cancel-payment"
export * from "./capture-payment"
export * from "./refund-payment"
4 changes: 2 additions & 2 deletions packages/core/types/src/payment/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ export interface IPaymentModuleService extends IModuleService {
* @param {string} id - The payment session's ID.
* @param {AuthorizePaymentSessionDTO} data - The attributes to authorize in a payment session.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<PaymentDTO>} The created payment.
* @returns {Promise<PaymentDTO | void>} The created payment or void when authorization is blocked.
*
* @example
* await paymentModuleService.authorizePaymentSession("payses_123", { provider_token: "" })
Expand All @@ -527,7 +527,7 @@ export interface IPaymentModuleService extends IModuleService {
id: string,
data?: AuthorizePaymentSessionDTO,
sharedContext?: Context
): Promise<PaymentDTO>
): Promise<PaymentDTO | void>

/**
* This method cancels a payment session.
Expand Down
31 changes: 11 additions & 20 deletions packages/modules/payment/src/services/payment-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,10 @@ export default class PaymentModuleService
id: string,
data?: AuthorizePaymentSessionDTO,
@MedusaContext() sharedContext?: Context
): Promise<PaymentDTO> {
const paymentSession = await this.paymentSessionService_.retrieve(
): Promise<PaymentDTO | void> {
let paymentSession = await this.paymentSessionService_.retrieve(
id,
{ select: ["data", "provider_id", "context"] },
{ select: ["data", "provider_id"] },
sharedContext
)

Expand All @@ -420,13 +420,12 @@ export default class PaymentModuleService
sharedContext
)

const payment = await this.paymentService_.retrieve(
{ payment_session_id: paymentSession.id },
{},
sharedContext
)

return this.baseRepository_.serialize(payment)
paymentSession = await this.paymentSessionService_.retrieve(id, {
relations: ["payment"],
})
if (paymentSession.payment) {
return this.baseRepository_.serialize<PaymentDTO>(paymentSession.payment)
}
}

@InjectManager("baseRepository_")
Expand Down Expand Up @@ -630,11 +629,7 @@ export default class PaymentModuleService

await this.handleProviderSessionResponse_(res, sharedContext)

return this.retrievePayment(
paymentId,
{ relations: ["captures"] },
sharedContext
)
return this.retrievePayment(paymentId, { relations: ["captures"] })
}

@InjectManager("baseRepository_")
Expand Down Expand Up @@ -743,11 +738,7 @@ export default class PaymentModuleService

await this.handleProviderSessionResponse_(res, sharedContext)

return this.retrievePayment(
paymentId,
{ relations: ["refunds"] },
sharedContext
)
return this.retrievePayment(paymentId, { relations: ["refunds"] })
}

@InjectManager("baseRepository_")
Expand Down

0 comments on commit 89ecdb4

Please sign in to comment.