feat: Add support for managing account holder in payment module (#11015)
This commit is contained in:
@@ -57,13 +57,13 @@ export const THREE_DAYS = 60 * 60 * 24 * 3
|
||||
|
||||
export const completeCartWorkflowId = "complete-cart"
|
||||
/**
|
||||
* This workflow completes a cart and places an order for the customer. It's executed by the
|
||||
* This workflow completes a cart and places an order for the customer. It's executed by the
|
||||
* [Complete Cart Store API Route](https://docs.medusajs.com/api/store#carts_postcartsidcomplete).
|
||||
*
|
||||
*
|
||||
* You can use this workflow within your own customizations or custom workflows, allowing you to wrap custom logic around completing a cart.
|
||||
* For example, in the [Subscriptions recipe](https://docs.medusajs.com/resources/recipes/subscriptions/examples/standard#create-workflow),
|
||||
* For example, in the [Subscriptions recipe](https://docs.medusajs.com/resources/recipes/subscriptions/examples/standard#create-workflow),
|
||||
* this workflow is used within another workflow that creates a subscription order.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* const { result } = await completeCartWorkflow(container)
|
||||
* .run({
|
||||
@@ -71,11 +71,11 @@ export const completeCartWorkflowId = "complete-cart"
|
||||
* id: "cart_123"
|
||||
* }
|
||||
* })
|
||||
*
|
||||
*
|
||||
* @summary
|
||||
*
|
||||
*
|
||||
* Complete a cart and place an order.
|
||||
*
|
||||
*
|
||||
* @property hooks.validate - This hook is executed before all operations. You can consume this hook to perform any custom validation. If validation fails, you can throw an error to stop the workflow execution.
|
||||
*/
|
||||
export const completeCartWorkflow = createWorkflow(
|
||||
@@ -118,7 +118,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, sales_channel_id } = transform({ cart }, (data) => {
|
||||
|
||||
@@ -26,14 +26,14 @@ export type ThrowUnlessPaymentCollectionNotePaidInput = {
|
||||
/**
|
||||
* This step validates that the payment collection is not paid. If not valid,
|
||||
* the step will throw an error.
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can retrieve a payment collection's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
|
||||
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* const data = throwUnlessPaymentCollectionNotPaid({
|
||||
* paymentCollection: {
|
||||
@@ -77,10 +77,10 @@ export const markPaymentCollectionAsPaidId = "mark-payment-collection-as-paid"
|
||||
/**
|
||||
* This workflow marks a payment collection for an order as paid. It's used by the
|
||||
* [Mark Payment Collection as Paid Admin API Route](https://docs.medusajs.com/api/admin#payment-collections_postpaymentcollectionsidmarkaspaid).
|
||||
*
|
||||
*
|
||||
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around
|
||||
* marking a payment collection for an order as paid.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* const { result } = await markPaymentCollectionAsPaid(container)
|
||||
* .run({
|
||||
@@ -89,16 +89,14 @@ export const markPaymentCollectionAsPaidId = "mark-payment-collection-as-paid"
|
||||
* payment_collection_id: "paycol_123",
|
||||
* }
|
||||
* })
|
||||
*
|
||||
*
|
||||
* @summary
|
||||
*
|
||||
*
|
||||
* Mark a payment collection for an order as paid.
|
||||
*/
|
||||
export const markPaymentCollectionAsPaid = createWorkflow(
|
||||
markPaymentCollectionAsPaidId,
|
||||
(
|
||||
input: WorkflowData<MarkPaymentCollectionAsPaidInput>
|
||||
) => {
|
||||
(input: WorkflowData<MarkPaymentCollectionAsPaidInput>) => {
|
||||
const paymentCollection = useRemoteQueryStep({
|
||||
entry_point: "payment_collection",
|
||||
fields: ["id", "status", "amount"],
|
||||
@@ -120,7 +118,6 @@ export const markPaymentCollectionAsPaid = createWorkflow(
|
||||
|
||||
const payment = authorizePaymentSessionStep({
|
||||
id: paymentSession.id,
|
||||
context: { order_id: input.order_id },
|
||||
})
|
||||
|
||||
capturePaymentWorkflow.runAsStep({
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import {
|
||||
IPaymentModuleService,
|
||||
CreateAccountHolderDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const createPaymentAccountHolderStepId = "create-payment-account-holder"
|
||||
/**
|
||||
* This step creates the account holder in the payment provider.
|
||||
*/
|
||||
export const createPaymentAccountHolderStep = createStep(
|
||||
createPaymentAccountHolderStepId,
|
||||
async (data: CreateAccountHolderDTO, { container }) => {
|
||||
const service = container.resolve<IPaymentModuleService>(Modules.PAYMENT)
|
||||
|
||||
const accountHolder = await service.createAccountHolder(data)
|
||||
|
||||
return new StepResponse(accountHolder, accountHolder)
|
||||
},
|
||||
async (createdAccountHolder, { container }) => {
|
||||
if (!createdAccountHolder) {
|
||||
return
|
||||
}
|
||||
|
||||
const service = container.resolve<IPaymentModuleService>(Modules.PAYMENT)
|
||||
await service.deleteAccountHolder(createdAccountHolder.id)
|
||||
}
|
||||
)
|
||||
@@ -24,7 +24,7 @@ export interface CreatePaymentSessionStepInput {
|
||||
amount: BigNumberInput
|
||||
/**
|
||||
* The currency code of the payment session.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* usd
|
||||
*/
|
||||
@@ -42,7 +42,7 @@ export interface CreatePaymentSessionStepInput {
|
||||
|
||||
export const createPaymentSessionStepId = "create-payment-session"
|
||||
/**
|
||||
* This step creates a payment session.
|
||||
* This step creates a payment session.
|
||||
*/
|
||||
export const createPaymentSessionStep = createStep(
|
||||
createPaymentSessionStepId,
|
||||
|
||||
@@ -5,3 +5,4 @@ export * from "./delete-refund-reasons"
|
||||
export * from "./update-payment-collection"
|
||||
export * from "./update-refund-reasons"
|
||||
export * from "./validate-deleted-payment-sessions"
|
||||
export * from "./create-payment-account-holder"
|
||||
|
||||
+95
-10
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
PaymentProviderContext,
|
||||
AccountHolderDTO,
|
||||
CustomerDTO,
|
||||
PaymentSessionDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
import {
|
||||
@@ -8,10 +9,15 @@ import {
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
transform,
|
||||
when,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
import { useRemoteQueryStep } from "../../common"
|
||||
import { createPaymentSessionStep } from "../steps"
|
||||
import { createRemoteLinkStep, useRemoteQueryStep } from "../../common"
|
||||
import {
|
||||
createPaymentSessionStep,
|
||||
createPaymentAccountHolderStep,
|
||||
} from "../steps"
|
||||
import { deletePaymentSessionsWorkflow } from "./delete-payment-sessions"
|
||||
import { isPresent, Modules } from "@medusajs/framework/utils"
|
||||
|
||||
/**
|
||||
* The data to create payment sessions.
|
||||
@@ -26,25 +32,31 @@ export interface CreatePaymentSessionsWorkflowInput {
|
||||
* This provider is used to later process the payment sessions and their payments.
|
||||
*/
|
||||
provider_id: string
|
||||
/**
|
||||
* The ID of the customer that the payment session should be associated with.
|
||||
*/
|
||||
customer_id?: string
|
||||
/**
|
||||
* Custom data relevant for the payment provider to process the payment session.
|
||||
* Learn more in [this documentation](https://docs.medusajs.com/resources/commerce-modules/payment/payment-session#data-property).
|
||||
*/
|
||||
data?: Record<string, unknown>
|
||||
|
||||
/**
|
||||
* Additional context that's useful for the payment provider to process the payment session.
|
||||
* Currently all of the context is calculated within the workflow.
|
||||
*/
|
||||
context?: PaymentProviderContext
|
||||
context?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export const createPaymentSessionsWorkflowId = "create-payment-sessions"
|
||||
/**
|
||||
* This workflow creates payment sessions. It's used by the
|
||||
* [Initialize Payment Session Store API Route](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollectionsidpaymentsessions).
|
||||
*
|
||||
*
|
||||
* You can use this workflow within your own customizations or custom workflows, allowing you
|
||||
* to create payment sessions in your custom flows.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* const { result } = await createPaymentSessionsWorkflow(container)
|
||||
* .run({
|
||||
@@ -53,9 +65,9 @@ export const createPaymentSessionsWorkflowId = "create-payment-sessions"
|
||||
* provider_id: "pp_system"
|
||||
* }
|
||||
* })
|
||||
*
|
||||
*
|
||||
* @summary
|
||||
*
|
||||
*
|
||||
* Create payment sessions.
|
||||
*/
|
||||
export const createPaymentSessionsWorkflow = createWorkflow(
|
||||
@@ -68,16 +80,89 @@ export const createPaymentSessionsWorkflow = createWorkflow(
|
||||
fields: ["id", "amount", "currency_code", "payment_sessions.*"],
|
||||
variables: { id: input.payment_collection_id },
|
||||
list: false,
|
||||
}).config({ name: "get-payment-collection" })
|
||||
|
||||
const { paymentCustomer, accountHolder } = when(
|
||||
"customer-id-exists",
|
||||
{ input },
|
||||
(data) => {
|
||||
return !!data.input.customer_id
|
||||
}
|
||||
).then(() => {
|
||||
const customer: CustomerDTO & { account_holder: AccountHolderDTO } =
|
||||
useRemoteQueryStep({
|
||||
entry_point: "customer",
|
||||
fields: [
|
||||
"id",
|
||||
"email",
|
||||
"company_name",
|
||||
"first_name",
|
||||
"last_name",
|
||||
"phone",
|
||||
"addresses.*",
|
||||
"account_holder.*",
|
||||
"metadata",
|
||||
],
|
||||
variables: { id: input.customer_id },
|
||||
list: false,
|
||||
}).config({ name: "get-customer" })
|
||||
|
||||
const paymentCustomer = transform({ customer }, (data) => {
|
||||
return {
|
||||
...data.customer,
|
||||
billing_address:
|
||||
data.customer.addresses?.find((a) => a.is_default_billing) ??
|
||||
data.customer.addresses?.[0],
|
||||
}
|
||||
})
|
||||
|
||||
const accountHolderInput = {
|
||||
provider_id: input.provider_id,
|
||||
context: {
|
||||
// The module is idempotent, so if there already is a linked account holder, the module will simply return it back.
|
||||
account_holder: customer.account_holder,
|
||||
customer: paymentCustomer,
|
||||
},
|
||||
}
|
||||
|
||||
const accountHolder = createPaymentAccountHolderStep(accountHolderInput)
|
||||
return { paymentCustomer, accountHolder }
|
||||
})
|
||||
|
||||
when(
|
||||
"account-holder-created",
|
||||
{ paymentCustomer, accountHolder },
|
||||
(data) => {
|
||||
return (
|
||||
!isPresent(data.paymentCustomer?.account_holder) &&
|
||||
isPresent(data.accountHolder)
|
||||
)
|
||||
}
|
||||
).then(() => {
|
||||
createRemoteLinkStep([
|
||||
{
|
||||
[Modules.CUSTOMER]: {
|
||||
customer_id: paymentCustomer.id,
|
||||
},
|
||||
[Modules.PAYMENT]: {
|
||||
account_holder_id: accountHolder.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
const paymentSessionInput = transform(
|
||||
{ paymentCollection, input },
|
||||
{ paymentCollection, paymentCustomer, accountHolder, 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,
|
||||
context: {
|
||||
...data.input.context,
|
||||
customer: data.paymentCustomer,
|
||||
account_holder: data.accountHolder,
|
||||
},
|
||||
amount: data.paymentCollection.amount,
|
||||
currency_code: data.paymentCollection.currency_code,
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ export type AuthorizePaymentSessionStepInput = {
|
||||
* The context to authorize the payment session with.
|
||||
* This context is passed to the payment provider associated with the payment session.
|
||||
*/
|
||||
context: Record<string, unknown>
|
||||
context?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export const authorizePaymentSessionStepId = "authorize-payment-session-step"
|
||||
/**
|
||||
* This step authorizes a payment session.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* const data = authorizePaymentSessionStep({
|
||||
* id: "payses_123",
|
||||
|
||||
@@ -31,12 +31,12 @@ export type CapturePaymentWorkflowInput = {
|
||||
|
||||
export const capturePaymentWorkflowId = "capture-payment-workflow"
|
||||
/**
|
||||
* This workflow captures a payment. It's used by the
|
||||
* This workflow captures a payment. It's used by the
|
||||
* [Capture Payment Admin API Route](https://docs.medusajs.com/api/admin#payments_postpaymentsidcapture).
|
||||
*
|
||||
*
|
||||
* You can use this workflow within your own customizations or custom workflows, allowing you
|
||||
* to capture a payment in your custom flows.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* const { result } = await capturePaymentWorkflow(container)
|
||||
* .run({
|
||||
@@ -44,9 +44,9 @@ export const capturePaymentWorkflowId = "capture-payment-workflow"
|
||||
* payment_id: "pay_123"
|
||||
* }
|
||||
* })
|
||||
*
|
||||
*
|
||||
* @summary
|
||||
*
|
||||
*
|
||||
* Capture a payment.
|
||||
*/
|
||||
export const capturePaymentWorkflow = createWorkflow(
|
||||
|
||||
@@ -8,15 +8,10 @@ export interface StoreInitializePaymentSession {
|
||||
* for.
|
||||
*/
|
||||
provider_id: string
|
||||
/**
|
||||
* The payment's context, such as the customer or address details. if the customer is logged-in,
|
||||
* the customer id is set in the context under a `customer.id` property.
|
||||
*/
|
||||
context?: Record<string, unknown>
|
||||
/**
|
||||
* Any data necessary for the payment provider to process the payment.
|
||||
*
|
||||
*
|
||||
* Learn more in [this documentation](https://docs.medusajs.com/resources/commerce-modules/payment/payment-session#data-property).
|
||||
*/
|
||||
data?: Record<string, unknown>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,3 +662,45 @@ export interface PaymentMethodDTO {
|
||||
*/
|
||||
provider_id: string
|
||||
}
|
||||
|
||||
export interface AccountHolderDTO {
|
||||
/**
|
||||
* The ID of the account holder.
|
||||
*/
|
||||
id: string
|
||||
|
||||
/**
|
||||
* The ID of the associated payment provider.
|
||||
*/
|
||||
provider_id: string
|
||||
|
||||
/**
|
||||
* The external ID of the account holder in the payment provider system.
|
||||
*/
|
||||
external_id: string
|
||||
|
||||
/**
|
||||
* The email of the account holder.
|
||||
*/
|
||||
email: string | null
|
||||
|
||||
/**
|
||||
* The data of the account holder, as returned by the payment provider.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
|
||||
/**
|
||||
* When the account holder was created.
|
||||
*/
|
||||
created_at?: string | Date | null
|
||||
|
||||
/**
|
||||
* When the account holder was updated.
|
||||
*/
|
||||
updated_at?: string | Date | null
|
||||
|
||||
/**
|
||||
* Holds custom data in key-value pairs.
|
||||
*/
|
||||
metadata?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BigNumberInput } from "../totals"
|
||||
import { PaymentCollectionStatus } from "./common"
|
||||
import { PaymentProviderContext } from "./provider"
|
||||
import { PaymentCustomerDTO, PaymentProviderContext } from "./provider"
|
||||
|
||||
/**
|
||||
* The payment collection to be created.
|
||||
@@ -255,6 +255,26 @@ export interface CreatePaymentProviderDTO {
|
||||
is_enabled?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The payment session to be created.
|
||||
*/
|
||||
export interface CreateAccountHolderDTO {
|
||||
/**
|
||||
* The provider's ID.
|
||||
*/
|
||||
provider_id: string
|
||||
|
||||
/**
|
||||
* Necessary context data for the associated payment provider.
|
||||
*/
|
||||
context: PaymentProviderContext & {
|
||||
/**
|
||||
* The customer information from Medusa.
|
||||
*/
|
||||
customer: PaymentCustomerDTO
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The details of the webhook event payload.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { AddressDTO } from "../address"
|
||||
import { CustomerDTO } from "../customer"
|
||||
import { BigNumberInput, BigNumberValue } from "../totals"
|
||||
import { PaymentSessionStatus } from "./common"
|
||||
import { AccountHolderDTO, PaymentSessionStatus } from "./common"
|
||||
import { ProviderWebhookPayload } from "./mutations"
|
||||
|
||||
/**
|
||||
@@ -12,7 +11,19 @@ export type PaymentAddressDTO = Partial<AddressDTO>
|
||||
/**
|
||||
* The customer associated with the payment.
|
||||
*/
|
||||
export type PaymentCustomerDTO = Partial<CustomerDTO>
|
||||
export type PaymentCustomerDTO = {
|
||||
id: string
|
||||
email: string
|
||||
company_name?: string | null
|
||||
first_name?: string | null
|
||||
last_name?: string | null
|
||||
phone?: string | null
|
||||
billing_address?: PaymentAddressDTO | null
|
||||
}
|
||||
|
||||
export type PaymentAccountHolderDTO = {
|
||||
data: Record<string, unknown>
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalized events from payment provider to internal payment module events.
|
||||
@@ -26,33 +37,26 @@ export type PaymentActions =
|
||||
/**
|
||||
* @interface
|
||||
*
|
||||
* Context data provided to the payment provider when authorizing a payment session.
|
||||
* Context data provided to the payment provider
|
||||
*/
|
||||
export type PaymentProviderContext = {
|
||||
/**
|
||||
* The payment's billing address.
|
||||
* The account holder information, if available for the payment provider.
|
||||
*/
|
||||
billing_address?: PaymentAddressDTO
|
||||
account_holder?: PaymentAccountHolderDTO
|
||||
|
||||
/**
|
||||
* The associated customer's email.
|
||||
*/
|
||||
email?: string
|
||||
|
||||
/**
|
||||
* The ID of payment session the provider payment is associated with.
|
||||
*/
|
||||
session_id?: string
|
||||
|
||||
/**
|
||||
* The customer associated with this payment.
|
||||
* The customer information from Medusa.
|
||||
*/
|
||||
customer?: PaymentCustomerDTO
|
||||
}
|
||||
|
||||
/**
|
||||
* The extra fields specific to the provider session.
|
||||
*/
|
||||
extra?: Record<string, unknown>
|
||||
export type PaymentProviderInput = {
|
||||
// Data is a combination of the input from the user and whatever is stored in the DB for this entity.
|
||||
data?: Record<string, unknown>
|
||||
|
||||
// The context for this payment operation. The data is guaranteed to be validated and not directly provided by the user.
|
||||
context?: PaymentProviderContext
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,12 +65,7 @@ export type PaymentProviderContext = {
|
||||
* The data used initiate a payment in a provider when a payment
|
||||
* session is created.
|
||||
*/
|
||||
export type CreatePaymentProviderSession = {
|
||||
/**
|
||||
* A context necessary for the payment provider.
|
||||
*/
|
||||
context: PaymentProviderContext
|
||||
|
||||
export type InitiatePaymentInput = PaymentProviderInput & {
|
||||
/**
|
||||
* The amount to be authorized.
|
||||
*/
|
||||
@@ -78,34 +77,12 @@ export type CreatePaymentProviderSession = {
|
||||
currency_code: string
|
||||
}
|
||||
|
||||
export type SavePaymentMethod = {
|
||||
/**
|
||||
* Any data that should be used by the provider for saving the payment method.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
|
||||
/**
|
||||
* The context of the payment provider, such as the customer ID.
|
||||
*/
|
||||
context: PaymentProviderContext
|
||||
}
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*
|
||||
* The attributes to update a payment related to a payment session in a provider.
|
||||
*/
|
||||
export type UpdatePaymentProviderSession = {
|
||||
/**
|
||||
* A payment's context.
|
||||
*/
|
||||
context: PaymentProviderContext
|
||||
|
||||
/**
|
||||
* The `data` field of the payment session.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
|
||||
export type UpdatePaymentInput = PaymentProviderInput & {
|
||||
/**
|
||||
* The payment session's amount.
|
||||
*/
|
||||
@@ -117,29 +94,58 @@ export type UpdatePaymentProviderSession = {
|
||||
currency_code: string
|
||||
}
|
||||
|
||||
export type DeletePaymentInput = PaymentProviderInput
|
||||
|
||||
export type AuthorizePaymentInput = PaymentProviderInput
|
||||
|
||||
export type CapturePaymentInput = PaymentProviderInput
|
||||
|
||||
export type RefundPaymentInput = PaymentProviderInput & {
|
||||
/**
|
||||
* The amount to refund.
|
||||
*/
|
||||
amount: BigNumberInput
|
||||
}
|
||||
|
||||
export type RetrievePaymentInput = PaymentProviderInput
|
||||
|
||||
export type CancelPaymentInput = PaymentProviderInput
|
||||
|
||||
export type CreateAccountHolderInput = PaymentProviderInput & {
|
||||
context: Omit<PaymentProviderContext, "customer"> & {
|
||||
customer: PaymentCustomerDTO
|
||||
}
|
||||
}
|
||||
|
||||
export type DeleteAccountHolderInput = PaymentProviderInput & {
|
||||
context: Omit<PaymentProviderContext, "account_holder"> & {
|
||||
account_holder: Partial<AccountHolderDTO>
|
||||
}
|
||||
}
|
||||
|
||||
export type ListPaymentMethodsInput = PaymentProviderInput
|
||||
|
||||
export type SavePaymentMethodInput = PaymentProviderInput
|
||||
|
||||
export type GetPaymentStatusInput = PaymentProviderInput
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*
|
||||
* The response of operations on a payment.
|
||||
*/
|
||||
export type PaymentProviderSessionResponse = {
|
||||
export type PaymentProviderOutput = {
|
||||
/**
|
||||
* The data to be stored in the `data` field of the Payment Session to be created.
|
||||
* The `data` field is useful to hold any data required by the third-party provider to process the payment or retrieve its details at a later point.
|
||||
* The unstrucvtured data returned from the payment provider. The content will vary between providers.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
data?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export type SavePaymentMethodResponse = {
|
||||
export type InitiatePaymentOutput = PaymentProviderOutput & {
|
||||
/**
|
||||
* The ID of the payment method in the payment provider.
|
||||
* The ID of the payment session in the payment provider.
|
||||
*/
|
||||
id: string
|
||||
|
||||
/**
|
||||
* The data returned from the payment provider after saving the payment method.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,59 +153,53 @@ export type SavePaymentMethodResponse = {
|
||||
*
|
||||
* The successful result of authorizing a payment session using a payment provider.
|
||||
*/
|
||||
export type PaymentProviderAuthorizeResponse = {
|
||||
export type AuthorizePaymentOutput = PaymentProviderOutput & {
|
||||
/**
|
||||
* The status of the payment, which will be stored in the payment session's `status` field.
|
||||
*/
|
||||
status: PaymentSessionStatus
|
||||
|
||||
/**
|
||||
* The `data` to be stored in the payment session's `data` field.
|
||||
*/
|
||||
data: PaymentProviderSessionResponse["data"]
|
||||
}
|
||||
|
||||
export type PaymentMethodResponse = {
|
||||
export type UpdatePaymentOutput = PaymentProviderOutput
|
||||
|
||||
export type DeletePaymentOutput = PaymentProviderOutput
|
||||
|
||||
export type CapturePaymentOutput = PaymentProviderOutput
|
||||
|
||||
export type RefundPaymentOutput = PaymentProviderOutput
|
||||
|
||||
export type RetrievePaymentOutput = PaymentProviderOutput
|
||||
|
||||
export type CancelPaymentOutput = PaymentProviderOutput
|
||||
|
||||
export type CreateAccountHolderOutput = PaymentProviderOutput & {
|
||||
/**
|
||||
* The ID of the account holder in the payment provider.
|
||||
*/
|
||||
id: string
|
||||
data: Record<string, unknown>
|
||||
}
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*
|
||||
* The details of which payment provider to use to perform an action, and what
|
||||
* data to be passed to that provider.
|
||||
*/
|
||||
export type PaymentProviderDataInput = {
|
||||
/**
|
||||
* The ID of the provider to be used to perform an action.
|
||||
*/
|
||||
provider_id: string
|
||||
export type DeleteAccountHolderOutput = PaymentProviderOutput
|
||||
|
||||
export type ListPaymentMethodsOutput = (PaymentProviderOutput & {
|
||||
/**
|
||||
* The data to be passed to the provider.
|
||||
* The ID of the payment method in the payment provider.
|
||||
*/
|
||||
data: Record<string, unknown>
|
||||
id: string
|
||||
})[]
|
||||
|
||||
export type SavePaymentMethodOutput = PaymentProviderOutput & {
|
||||
/**
|
||||
* The ID of the payment method in the payment provider.
|
||||
*/
|
||||
id: string
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that is returned in case of an error.
|
||||
*/
|
||||
export interface PaymentProviderError {
|
||||
export type GetPaymentStatusOutput = PaymentProviderOutput & {
|
||||
/**
|
||||
* The error message
|
||||
* The status of the payment, which will be stored in the payment session's `status` field.
|
||||
*/
|
||||
error: string
|
||||
|
||||
/**
|
||||
* The error code.
|
||||
*/
|
||||
code?: string
|
||||
|
||||
/**
|
||||
* Any additional helpful details.
|
||||
*/
|
||||
detail?: any
|
||||
status: PaymentSessionStatus
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,51 +244,39 @@ export interface IPaymentProvider {
|
||||
*/
|
||||
getIdentifier(): string
|
||||
|
||||
initiatePayment(
|
||||
data: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
initiatePayment(data: InitiatePaymentInput): Promise<InitiatePaymentOutput>
|
||||
|
||||
updatePayment(
|
||||
context: UpdatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
updatePayment(data: UpdatePaymentInput): Promise<UpdatePaymentOutput>
|
||||
|
||||
deletePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
deletePayment(data: DeletePaymentInput): Promise<DeletePaymentOutput>
|
||||
|
||||
authorizePayment(
|
||||
paymentSessionData: Record<string, unknown>,
|
||||
context: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderAuthorizeResponse>
|
||||
authorizePayment(data: AuthorizePaymentInput): Promise<AuthorizePaymentOutput>
|
||||
|
||||
capturePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
capturePayment(data: CapturePaymentInput): Promise<CapturePaymentOutput>
|
||||
|
||||
refundPayment(
|
||||
paymentSessionData: Record<string, unknown>,
|
||||
refundAmount: BigNumberInput
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
refundPayment(data: RefundPaymentInput): Promise<RefundPaymentOutput>
|
||||
|
||||
retrievePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
retrievePayment(data: RetrievePaymentInput): Promise<RetrievePaymentOutput>
|
||||
|
||||
cancelPayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
cancelPayment(data: CancelPaymentInput): Promise<CancelPaymentOutput>
|
||||
|
||||
createAccountHolder?(
|
||||
data: CreateAccountHolderInput
|
||||
): Promise<CreateAccountHolderOutput>
|
||||
|
||||
deleteAccountHolder?(
|
||||
data: DeleteAccountHolderInput
|
||||
): Promise<DeleteAccountHolderOutput>
|
||||
|
||||
listPaymentMethods?(
|
||||
context: PaymentProviderContext
|
||||
): Promise<PaymentMethodResponse[]>
|
||||
data: ListPaymentMethodsInput
|
||||
): Promise<ListPaymentMethodsOutput>
|
||||
|
||||
savePaymentMethod?(
|
||||
input: SavePaymentMethod
|
||||
): Promise<PaymentProviderError | SavePaymentMethodResponse>
|
||||
data: SavePaymentMethodInput
|
||||
): Promise<SavePaymentMethodOutput>
|
||||
|
||||
getPaymentStatus(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentSessionStatus>
|
||||
getPaymentStatus(data: GetPaymentStatusInput): Promise<GetPaymentStatusOutput>
|
||||
|
||||
getWebhookActionAndData(
|
||||
data: ProviderWebhookPayload["payload"]
|
||||
|
||||
@@ -3,6 +3,7 @@ import { RestoreReturn, SoftDeleteReturn } from "../dal"
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import { Context } from "../shared-context"
|
||||
import {
|
||||
AccountHolderDTO,
|
||||
CaptureDTO,
|
||||
FilterableCaptureProps,
|
||||
FilterablePaymentCollectionProps,
|
||||
@@ -31,6 +32,7 @@ import {
|
||||
UpdatePaymentDTO,
|
||||
UpdatePaymentSessionDTO,
|
||||
UpdateRefundReasonDTO,
|
||||
CreateAccountHolderDTO,
|
||||
UpsertPaymentCollectionDTO,
|
||||
} from "./mutations"
|
||||
import { WebhookActionResult } from "./provider"
|
||||
@@ -751,6 +753,63 @@ export interface IPaymentModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<[PaymentProviderDTO[], number]>
|
||||
|
||||
/**
|
||||
* This method creates(if supported by provider) the account holder in the payment provider.
|
||||
*
|
||||
* @param {CreateAccountHolderDTO} data - The details of the account holder.
|
||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||
* @returns {Promise<Record<string, unknown>>} The account holder's details in the payment provider, typically just the ID.
|
||||
*
|
||||
* @example
|
||||
* const accountHolder =
|
||||
* await paymentModuleService.createAccountHolder(
|
||||
* {
|
||||
* provider_id: "stripe",
|
||||
* context: {
|
||||
* customer: {
|
||||
* id: "cus_123",
|
||||
* },
|
||||
* },
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* remoteLink.create([{
|
||||
* [Modules.CUSTOMER]: {
|
||||
* customer_id: "cus_123",
|
||||
* },
|
||||
* [Modules.PAYMENT]: {
|
||||
* account_holder_id: accountHolder.id,
|
||||
* },
|
||||
* }])
|
||||
*/
|
||||
createAccountHolder(
|
||||
input: CreateAccountHolderDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<AccountHolderDTO>
|
||||
|
||||
/**
|
||||
* This method deletes the account holder in the payment provider.
|
||||
*
|
||||
* @param {string} id - The account holder's ID.
|
||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||
* @returns {Promise<void>} Resolves when the account holder is deleted successfully.
|
||||
*
|
||||
* @example
|
||||
* await paymentModuleService.deleteAccountHolder({
|
||||
* id: "acc_holder_123",
|
||||
* })
|
||||
*
|
||||
* remoteLink.dismiss([{
|
||||
* [Modules.CUSTOMER]: {
|
||||
* customer_id: "cus_123",
|
||||
* },
|
||||
* [Modules.PAYMENT]: {
|
||||
* account_holder_id: "acc_holder_123",
|
||||
* },
|
||||
* }])
|
||||
*/
|
||||
deleteAccountHolder(id: string, sharedContext?: Context): Promise<void>
|
||||
|
||||
/**
|
||||
* This method retrieves all payment methods based on the context and configuration.
|
||||
*
|
||||
|
||||
@@ -122,4 +122,10 @@ export const LINKS = {
|
||||
Modules.FULFILLMENT,
|
||||
"shipping_profile_id"
|
||||
),
|
||||
CustomerAccountHolder: composeLinkName(
|
||||
Modules.CUSTOMER,
|
||||
"customer_id",
|
||||
Modules.PAYMENT,
|
||||
"account_holder_id"
|
||||
),
|
||||
}
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
import {
|
||||
CreatePaymentProviderSession,
|
||||
IPaymentProvider,
|
||||
PaymentProviderError,
|
||||
PaymentProviderSessionResponse,
|
||||
PaymentSessionStatus,
|
||||
ProviderWebhookPayload,
|
||||
UpdatePaymentProviderSession,
|
||||
WebhookActionResult,
|
||||
CapturePaymentInput,
|
||||
CapturePaymentOutput,
|
||||
AuthorizePaymentInput,
|
||||
AuthorizePaymentOutput,
|
||||
CancelPaymentInput,
|
||||
CancelPaymentOutput,
|
||||
InitiatePaymentInput,
|
||||
InitiatePaymentOutput,
|
||||
DeletePaymentInput,
|
||||
DeletePaymentOutput,
|
||||
GetPaymentStatusInput,
|
||||
GetPaymentStatusOutput,
|
||||
RefundPaymentInput,
|
||||
RefundPaymentOutput,
|
||||
RetrievePaymentInput,
|
||||
RetrievePaymentOutput,
|
||||
UpdatePaymentInput,
|
||||
UpdatePaymentOutput,
|
||||
} from "@medusajs/types"
|
||||
|
||||
export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
@@ -147,48 +160,34 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
*
|
||||
* In this method, use the third-party provider to capture the payment.
|
||||
*
|
||||
* @param paymentData - The `data` property of the payment. Make sure to store in it
|
||||
* any helpful identification for your third-party integration.
|
||||
* @returns The new data to store in the payment's `data` property, or an error object.
|
||||
* @param input - The input to capture the payment. The `data` field should contain the data from the payment provider. when the payment was created.
|
||||
* @returns The new data to store in the payment's `data` property. Throws in case of an error.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* PaymentProviderError,
|
||||
* PaymentProviderSessionResponse,
|
||||
* CapturePaymentInput,
|
||||
* CapturePaymentOutput,
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
* class MyPaymentProviderService extends AbstractPaymentProvider<
|
||||
* Options
|
||||
* > {
|
||||
* async capturePayment(
|
||||
* paymentData: Record<string, unknown>
|
||||
* ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]> {
|
||||
* const externalId = paymentData.id
|
||||
* input: CapturePaymentInput
|
||||
* ): Promise<CapturePaymentOutput> {
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that captures the payment
|
||||
* const newData = await this.client.capturePayment(externalId)
|
||||
*
|
||||
* return {
|
||||
* ...newData,
|
||||
* id: externalId
|
||||
* }
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* }
|
||||
* const newData = await this.client.capturePayment(externalId)
|
||||
* return {data: newData}
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
abstract capturePayment(
|
||||
paymentData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
input: CapturePaymentInput
|
||||
): Promise<CapturePaymentOutput>
|
||||
|
||||
/**
|
||||
* This method authorizes a payment session. When authorized successfully, a payment is created by the Payment
|
||||
@@ -199,18 +198,14 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
*
|
||||
* To automatically capture the payment after authorization, return the status `captured`.
|
||||
*
|
||||
* @param paymentSessionData - The `data` property of the payment session. Make sure to store in it
|
||||
* any helpful identification for your third-party integration.
|
||||
* @param context - The context in which the payment is being authorized. For example, in checkout,
|
||||
* the context has a `cart_id` property indicating the ID of the associated cart.
|
||||
* @returns Either an object of the new data to store in the created payment's `data` property and the
|
||||
* payment's status, or an error object. Make sure to set in `data` anything useful to later retrieve the session.
|
||||
* @param input - The input to authorize the payment. The `data` field should contain the data from the payment provider. when the payment was created.
|
||||
* @returns The status of the authorization, along with the `data` field about the payment. Throws in case of an error.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* PaymentProviderError,
|
||||
* PaymentProviderSessionResponse,
|
||||
* AuthorizePaymentInput,
|
||||
* AuthorizePaymentOutput,
|
||||
* PaymentSessionStatus
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
@@ -219,33 +214,16 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async authorizePayment(
|
||||
* paymentSessionData: Record<string, unknown>,
|
||||
* context: Record<string, unknown>
|
||||
* ): Promise<
|
||||
* PaymentProviderError | {
|
||||
* status: PaymentSessionStatus
|
||||
* data: PaymentProviderSessionResponse["data"]
|
||||
* }
|
||||
* > {
|
||||
* const externalId = paymentSessionData.id
|
||||
* input: AuthorizePaymentInput
|
||||
* ): Promise<AuthorizePaymentOutput> {
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that authorizes the payment
|
||||
* const paymentData = await this.client.authorizePayment(externalId)
|
||||
* // assuming you have a client that authorizes the payment
|
||||
* const paymentData = await this.client.authorizePayment(externalId)
|
||||
*
|
||||
* return {
|
||||
* data: {
|
||||
* ...paymentData,
|
||||
* id: externalId
|
||||
* },
|
||||
* status: "authorized"
|
||||
* }
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* return {
|
||||
* data: paymentData,
|
||||
* status: "authorized"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
@@ -253,28 +231,14 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* }
|
||||
*/
|
||||
abstract authorizePayment(
|
||||
paymentSessionData: Record<string, unknown>,
|
||||
context: Record<string, unknown>
|
||||
): Promise<
|
||||
| PaymentProviderError
|
||||
| {
|
||||
/**
|
||||
* The new status of the payment.
|
||||
*/
|
||||
status: PaymentSessionStatus
|
||||
/**
|
||||
* The data to store in the created payment's `data` property.
|
||||
*/
|
||||
data: PaymentProviderSessionResponse["data"]
|
||||
}
|
||||
>
|
||||
input: AuthorizePaymentInput
|
||||
): Promise<AuthorizePaymentOutput>
|
||||
|
||||
/**
|
||||
* This method cancels a payment.
|
||||
*
|
||||
* @param paymentData - The `data` property of the payment. Make sure to store in it
|
||||
* any helpful identification for your third-party integration.
|
||||
* @returns An error object if an error occurs, or the data received from the integration.
|
||||
* @param input - The input to cancel the payment. The `data` field should contain the data from the payment provider. when the payment was created.
|
||||
* @returns The new data to store in the payment's `data` property, if any. Throws in case of an error.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
@@ -288,42 +252,34 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async cancelPayment(
|
||||
* paymentData: Record<string, unknown>
|
||||
* ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]> {
|
||||
* const externalId = paymentData.id
|
||||
* input: CancelPaymentInput
|
||||
* ): Promise<CancelPaymentOutput> {
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that cancels the payment
|
||||
* const paymentData = await this.client.cancelPayment(externalId)
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* }
|
||||
* // assuming you have a client that cancels the payment
|
||||
* const paymentData = await this.client.cancelPayment(externalId)
|
||||
* return { data: paymentData }
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
abstract cancelPayment(
|
||||
paymentData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
input: CancelPaymentInput
|
||||
): Promise<CancelPaymentOutput>
|
||||
|
||||
/**
|
||||
* This method is used when a payment session is created. It can be used to initiate the payment
|
||||
* in the third-party session, before authorizing or capturing the payment later.
|
||||
*
|
||||
* @param context - The details of the payment session and its context.
|
||||
* @returns An object whose `data` property is set in the created payment session, or an error
|
||||
* object. Make sure to set in `data` anything useful to later retrieve the session.
|
||||
* @param input - The input to create the payment session.
|
||||
* @returns The new data to store in the payment's `data` property. Throws in case of an error.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* PaymentProviderError,
|
||||
* PaymentProviderSessionResponse,
|
||||
* InitiatePaymentInput,
|
||||
* InitiatePaymentOutput,
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
*
|
||||
@@ -331,32 +287,22 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async initiatePayment(
|
||||
* context: CreatePaymentProviderSession
|
||||
* ): Promise<PaymentProviderError | PaymentProviderSessionResponse> {
|
||||
* input: InitiatePaymentInput
|
||||
* ): Promise<InitiatePaymentOutput> {
|
||||
* const {
|
||||
* amount,
|
||||
* currency_code,
|
||||
* context: customerDetails
|
||||
* } = context
|
||||
* } = input
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that initializes the payment
|
||||
* const response = await this.client.init(
|
||||
* amount, currency_code, customerDetails
|
||||
* )
|
||||
* // assuming you have a client that initializes the payment
|
||||
* const response = await this.client.init(
|
||||
* amount, currency_code, customerDetails
|
||||
* )
|
||||
*
|
||||
* return {
|
||||
* ...response,
|
||||
* data: {
|
||||
* id: response.id
|
||||
* }
|
||||
* }
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* return {
|
||||
* id: response.id
|
||||
* data: response,
|
||||
* }
|
||||
* }
|
||||
*
|
||||
@@ -364,23 +310,22 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* }
|
||||
*/
|
||||
abstract initiatePayment(
|
||||
context: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
input: InitiatePaymentInput
|
||||
): Promise<InitiatePaymentOutput>
|
||||
|
||||
/**
|
||||
* This method is used when a payment session is deleted, which can only happen if it isn't authorized, yet.
|
||||
*
|
||||
* Use this to delete or cancel the payment in the third-party service.
|
||||
*
|
||||
* @param paymentSessionData - The `data` property of the payment session. Make sure to store in it
|
||||
* any helpful identification for your third-party integration.
|
||||
* @returns An error object or the response from the third-party service.
|
||||
* @param input - The input to delete the payment session. The `data` field should contain the data from the payment provider. when the payment was created.
|
||||
* @returns The new data to store in the payment's `data` property, if any. Throws in case of an error.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* PaymentProviderError,
|
||||
* PaymentProviderSessionResponse,
|
||||
* DeletePaymentInput,
|
||||
* DeletePaymentOutput,
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
*
|
||||
@@ -388,41 +333,34 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async deletePayment(
|
||||
* paymentSessionData: Record<string, unknown>
|
||||
* ): Promise<
|
||||
* PaymentProviderError | PaymentProviderSessionResponse["data"]
|
||||
* > {
|
||||
* const externalId = paymentSessionData.id
|
||||
* input: DeletePaymentInput
|
||||
* ): Promise<DeletePaymentOutput> {
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that cancels the payment
|
||||
* await this.client.cancelPayment(externalId)
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* }
|
||||
* // assuming you have a client that cancels the payment
|
||||
* await this.client.cancelPayment(externalId)
|
||||
* return {}
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
abstract deletePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
input: DeletePaymentInput
|
||||
): Promise<DeletePaymentOutput>
|
||||
|
||||
/**
|
||||
* This method gets the status of a payment session based on the status in the third-party integration.
|
||||
*
|
||||
* @param paymentSessionData - The `data` property of the payment session. Make sure to store in it
|
||||
* any helpful identification for your third-party integration.
|
||||
* @returns The payment session's status.
|
||||
* @param input - The input to get the payment status. The `data` field should contain the data from the payment provider. when the payment was created.
|
||||
* @returns The payment session's status. It can also return additional `data` from the payment provider.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* GetPaymentStatusInput,
|
||||
* GetPaymentStatusOutput,
|
||||
* PaymentSessionStatus
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
@@ -431,49 +369,43 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async getPaymentStatus(
|
||||
* paymentSessionData: Record<string, unknown>
|
||||
* ): Promise<PaymentSessionStatus> {
|
||||
* const externalId = paymentSessionData.id
|
||||
* input: GetPaymentStatusInput
|
||||
* ): Promise<GetPaymentStatusOutput> {
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that retrieves the payment status
|
||||
* const status = await this.client.getStatus(externalId)
|
||||
* // assuming you have a client that retrieves the payment status
|
||||
* const status = await this.client.getStatus(externalId)
|
||||
*
|
||||
* switch (status) {
|
||||
* case "requires_capture":
|
||||
* return "authorized"
|
||||
* switch (status) {
|
||||
* case "requires_capture":
|
||||
* return {status: "authorized"}
|
||||
* case "success":
|
||||
* return "captured"
|
||||
* return {status: "captured"}
|
||||
* case "canceled":
|
||||
* return "canceled"
|
||||
* return {status: "canceled"}
|
||||
* default:
|
||||
* return "pending"
|
||||
* }
|
||||
* } catch (e) {
|
||||
* return "error"
|
||||
* }
|
||||
* return {status: "pending"}
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
abstract getPaymentStatus(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentSessionStatus>
|
||||
input: GetPaymentStatusInput
|
||||
): Promise<GetPaymentStatusOutput>
|
||||
|
||||
/**
|
||||
* This method refunds an amount of a payment previously captured.
|
||||
*
|
||||
* @param paymentData - The `data` property of the payment. Make sure to store in it
|
||||
* any helpful identification for your third-party integration.
|
||||
* @param refundAmount The amount to refund.
|
||||
* @param input - The input to refund the payment. The `data` field should contain the data from the payment provider. when the payment was created.
|
||||
* @returns The new data to store in the payment's `data` property, or an error object.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* PaymentProviderError,
|
||||
* PaymentProviderSessionResponse,
|
||||
* RefundPaymentInput,
|
||||
* RefundPaymentOutput,
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
*
|
||||
@@ -481,53 +413,36 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async refundPayment(
|
||||
* paymentData: Record<string, unknown>,
|
||||
* refundAmount: number
|
||||
* ): Promise<
|
||||
* PaymentProviderError | PaymentProviderSessionResponse["data"]
|
||||
* > {
|
||||
* const externalId = paymentData.id
|
||||
* input: RefundPaymentInput
|
||||
* ): Promise<RefundPaymentOutput> {
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that refunds the payment
|
||||
* const newData = await this.client.refund(
|
||||
* // assuming you have a client that refunds the payment
|
||||
* const newData = await this.client.refund(
|
||||
* externalId,
|
||||
* refundAmount
|
||||
* input.amount
|
||||
* )
|
||||
*
|
||||
* return {
|
||||
* ...newData,
|
||||
* id: externalId
|
||||
* }
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* }
|
||||
* return {data: newData}
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
abstract refundPayment(
|
||||
paymentData: Record<string, unknown>,
|
||||
refundAmount: number
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
input: RefundPaymentInput
|
||||
): Promise<RefundPaymentOutput>
|
||||
|
||||
/**
|
||||
* Retrieves the payment's data from the third-party service.
|
||||
*
|
||||
* @param paymentSessionData - The `data` property of the payment. Make sure to store in it
|
||||
* any helpful identification for your third-party integration.
|
||||
* @returns An object to be stored in the payment's `data` property, or an error object.
|
||||
* @param input - The input to retrieve the payment. The `data` field should contain the data from the payment provider when the payment was created.
|
||||
* @returns The payment's data as found in the the payment provider.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* PaymentProviderError,
|
||||
* PaymentProviderSessionResponse,
|
||||
* RetrievePaymentInput,
|
||||
* RetrievePaymentOutput,
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
*
|
||||
@@ -535,44 +450,31 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async retrievePayment(
|
||||
* paymentSessionData: Record<string, unknown>
|
||||
* ): Promise<
|
||||
* PaymentProviderError | PaymentProviderSessionResponse["data"]
|
||||
* > {
|
||||
* const externalId = paymentSessionData.id
|
||||
* input: RetrievePaymentInput
|
||||
* ): Promise<RetrievePaymentOutput> {
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that retrieves the payment
|
||||
* return await this.client.retrieve(externalId)
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* }
|
||||
* // assuming you have a client that retrieves the payment
|
||||
* return await this.client.retrieve(externalId)
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
abstract retrievePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
input: RetrievePaymentInput
|
||||
): Promise<RetrievePaymentOutput>
|
||||
|
||||
/**
|
||||
* Update a payment in the third-party service that was previously initiated with the {@link initiatePayment} method.
|
||||
*
|
||||
* @param context - The details of the payment session and its context.
|
||||
* @returns An object whose `data` property is set in the updated payment session, or an error
|
||||
* object. Make sure to set in `data` anything useful to later retrieve the session.
|
||||
* @param input - The input to update the payment. The `data` field should contain the data from the payment provider. when the payment was created.
|
||||
* @returns The new data to store in the payment's `data` property. Throws in case of an error.
|
||||
*
|
||||
* @example
|
||||
* // other imports...
|
||||
* import {
|
||||
* UpdatePaymentProviderSession,
|
||||
* PaymentProviderError,
|
||||
* PaymentProviderSessionResponse,
|
||||
* UpdatePaymentInput,
|
||||
* UpdatePaymentOutput,
|
||||
* } from "@medusajs/framework/types"
|
||||
*
|
||||
*
|
||||
@@ -580,48 +482,30 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
* Options
|
||||
* > {
|
||||
* async updatePayment(
|
||||
* context: UpdatePaymentProviderSession
|
||||
* ): Promise<PaymentProviderError | PaymentProviderSessionResponse> {
|
||||
* const {
|
||||
* amount,
|
||||
* currency_code,
|
||||
* context: customerDetails,
|
||||
* data
|
||||
* } = context
|
||||
* const externalId = data.id
|
||||
* input: UpdatePaymentInput
|
||||
* ): Promise<UpdatePaymentOutput> {
|
||||
* const { amount, currency_code, context } = input
|
||||
* const externalId = input.data?.id
|
||||
*
|
||||
* try {
|
||||
* // assuming you have a client that updates the payment
|
||||
* const response = await this.client.update(
|
||||
* externalId,
|
||||
* // assuming you have a client that updates the payment
|
||||
* const response = await this.client.update(
|
||||
* externalId,
|
||||
* {
|
||||
* amount,
|
||||
* currency_code,
|
||||
* customerDetails
|
||||
* context.customer
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* return {
|
||||
* ...response,
|
||||
* data: {
|
||||
* id: response.id
|
||||
* }
|
||||
* }
|
||||
* } catch (e) {
|
||||
* return {
|
||||
* error: e,
|
||||
* code: "unknown",
|
||||
* detail: e
|
||||
* }
|
||||
* }
|
||||
* return response
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
abstract updatePayment(
|
||||
context: UpdatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
input: UpdatePaymentInput
|
||||
): Promise<UpdatePaymentOutput>
|
||||
|
||||
/**
|
||||
* This method is executed when a webhook event is received from the third-party payment provider. Use it
|
||||
|
||||
Reference in New Issue
Block a user