From 18f7b71b1bf114918189a5fccc14c7ca1f289f78 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Fri, 31 Jan 2025 11:39:10 +0200 Subject: [PATCH] chore(core-flows,types): update TSDocs following latest payment changes (#11241) --- .../steps/create-payment-account-holder.ts | 11 + packages/core/types/src/payment/provider.ts | 308 +++++++++++++++++- 2 files changed, 315 insertions(+), 4 deletions(-) diff --git a/packages/core/core-flows/src/payment-collection/steps/create-payment-account-holder.ts b/packages/core/core-flows/src/payment-collection/steps/create-payment-account-holder.ts index cb820a357b..38979c53c1 100644 --- a/packages/core/core-flows/src/payment-collection/steps/create-payment-account-holder.ts +++ b/packages/core/core-flows/src/payment-collection/steps/create-payment-account-holder.ts @@ -8,6 +8,17 @@ 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. + * + * @example + * const accountHolder = createPaymentAccountHolderStep({ + * provider_id: "pp_stripe_stripe", + * context: { + * customer: { + * id: "cus_123", + * email: "example@gmail.com" + * } + * } + * }) */ export const createPaymentAccountHolderStep = createStep( createPaymentAccountHolderStepId, diff --git a/packages/core/types/src/payment/provider.ts b/packages/core/types/src/payment/provider.ts index a976f9b47d..58d5b5a3b2 100644 --- a/packages/core/types/src/payment/provider.ts +++ b/packages/core/types/src/payment/provider.ts @@ -12,16 +12,40 @@ export type PaymentAddressDTO = Partial * The customer associated with the payment. */ export type PaymentCustomerDTO = { + /** + * The ID of the customer in Medusa. + */ id: string + /** + * The email of the customer. + */ email: string + /** + * The customer's company name. + */ company_name?: string | null + /** + * The customer's first name. + */ first_name?: string | null + /** + * The customer's last name. + */ last_name?: string | null + /** + * The customer's phone number. + */ phone?: string | null + /** + * The customer's billing address. + */ billing_address?: PaymentAddressDTO | null } export type PaymentAccountHolderDTO = { + /** + * Account holder's details as stored in the third-party payment provider. + */ data: Record } @@ -52,10 +76,13 @@ export type PaymentProviderContext = { } export type PaymentProviderInput = { - // Data is a combination of the input from the user and whatever is stored in the DB for this entity. + /** + * Data is a combination of the input from the user and what is stored in the database for the associated model. + */ data?: Record - - // The context for this payment operation. The data is guaranteed to be validated and not directly provided by the user. + /** + * The context for this payment operation. The data is guaranteed to be validated and not directly provided by the user. + */ context?: PaymentProviderContext } @@ -94,12 +121,32 @@ export type UpdatePaymentInput = PaymentProviderInput & { currency_code: string } +/** + * @interface + * + * The data to delete a payment. + */ export type DeletePaymentInput = PaymentProviderInput +/** + * @interface + * + * The data to authorize a payment. + */ export type AuthorizePaymentInput = PaymentProviderInput +/** + * @interface + * + * The data to capture a payment. + */ export type CapturePaymentInput = PaymentProviderInput +/** + * @interface + * + * The data to refund a payment. + */ export type RefundPaymentInput = PaymentProviderInput & { /** * The amount to refund. @@ -107,26 +154,73 @@ export type RefundPaymentInput = PaymentProviderInput & { amount: BigNumberInput } +/** + * @interface + * + * The data to retrieve a payment. + */ export type RetrievePaymentInput = PaymentProviderInput +/** + * @interface + * + * The data to cancel a payment. + */ export type CancelPaymentInput = PaymentProviderInput +/** + * @interface + * + * The data to create an account holder. + */ export type CreateAccountHolderInput = PaymentProviderInput & { + /** + * The context of creating the account holder. + */ context: Omit & { + /** + * The account holder's associated customer details. + */ customer: PaymentCustomerDTO } } +/** + * @interface + * + * The data to delete an account holder. + */ export type DeleteAccountHolderInput = PaymentProviderInput & { + /** + * The context of deleting the account holder. + */ context: Omit & { + /** + * The account holder's details. + */ account_holder: Partial } } +/** + * @interface + * + * The data to list payment methods. + */ export type ListPaymentMethodsInput = PaymentProviderInput +/** + * @interface + * + * The data to save a payment method. + */ export type SavePaymentMethodInput = PaymentProviderInput +/** + * @interface + * + * The data to get the payment status. + */ export type GetPaymentStatusInput = PaymentProviderInput /** @@ -136,11 +230,16 @@ export type GetPaymentStatusInput = PaymentProviderInput */ export type PaymentProviderOutput = { /** - * The unstrucvtured data returned from the payment provider. The content will vary between providers. + * The unstructured data returned from the payment provider. The content will vary between providers. */ data?: Record } +/** + * @interface + * + * The successful result of initiating a payment session using a third-party payment provider. + */ export type InitiatePaymentOutput = PaymentProviderOutput & { /** * The ID of the payment session in the payment provider. @@ -160,21 +259,58 @@ export type AuthorizePaymentOutput = PaymentProviderOutput & { status: PaymentSessionStatus } +/** + * @interface + * + * The result of updating a payment. + */ export type UpdatePaymentOutput = PaymentProviderOutput +/** + * @interface + * + * The result of deleting a payment. + */ export type DeletePaymentOutput = PaymentProviderOutput +/** + * @interface + * + * The result of capturing the payment. + */ export type CapturePaymentOutput = PaymentProviderOutput +/** + * @interface + * + * The result of refunding the payment. + */ export type RefundPaymentOutput = PaymentProviderOutput +/** + * @interface + * + * The result of retrieving the payment. + */ export type RetrievePaymentOutput = PaymentProviderOutput +/** + * @interface + * + * The result of canceling the payment. + */ export type CancelPaymentOutput = PaymentProviderOutput +/** + * @interface + * + * The result of creating an account holder in the third-party payment provider. The `data` + * property is stored as-is in Medusa's account holder's `data` property. + */ export type CreateAccountHolderOutput = PaymentProviderOutput & { /** * The ID of the account holder in the payment provider. + * This is stored in Medusa's account holder in the `external_id` property. */ id: string } @@ -188,6 +324,11 @@ export type ListPaymentMethodsOutput = (PaymentProviderOutput & { id: string })[] +/** + * @interface + * + * The result of saving a payment method. + */ export type SavePaymentMethodOutput = PaymentProviderOutput & { /** * The ID of the payment method in the payment provider. @@ -195,6 +336,11 @@ export type SavePaymentMethodOutput = PaymentProviderOutput & { id: string } +/** + * @interface + * + * The result of getting the payment status. + */ export type GetPaymentStatusOutput = PaymentProviderOutput & { /** * The status of the payment, which will be stored in the payment session's `status` field. @@ -260,18 +406,172 @@ export interface IPaymentProvider { cancelPayment(data: CancelPaymentInput): Promise + /** + * This method is used when creating an account holder in Medusa, allowing you to create + * the equivalent account in the third-party service. An account holder is useful to + * later save payment methods, such as credit cards, for a customer in the + * third-party payment provider using the {@link savePaymentMethod} method. + * + * The returned data will be stored in the account holder created in Medusa. For example, + * the returned `id` property will be stored in the account holder's `external_id` property. + * + * Medusa creates an account holder when a payment session initialized for a registered customer. + * + * @param data - Input data including the details of the account holder to create. + * @returns The result of creating the account holder. If an error occurs, throw it. + * + * @example + * import { MedusaError } from "@medusajs/framework/utils" + * + * class MyPaymentProviderService extends AbstractPaymentProvider< + * Options + * > { + * async createAccountHolder({ context, data }: CreateAccountHolderInput) { + * const { account_holder, customer } = context + * + * if (account_holder?.data?.id) { + * return { id: account_holder.data.id as string } + * } + * + * if (!customer) { + * throw new MedusaError( + * MedusaError.Types.INVALID_DATA, + * "Missing customer data." + * ) + * } + * + * // assuming you have a client that creates the account holder + * const providerAccountHolder = await this.client.createAccountHolder({ + * email: customer.email, + * ...data + * }) + * + * return { + * id: providerAccountHolder.id, + * data: providerAccountHolder as unknown as Record + * } + * } + */ createAccountHolder?( data: CreateAccountHolderInput ): Promise + /** + * This method is used when an account holder is deleted in Medusa, allowing you + * to also delete the equivalent account holder in the third-party service. + * + * @param data - Input data including the details of the account holder to delete. + * @returns The result of deleting the account holder. If an error occurs, throw it. + * + * @example + * import { MedusaError } from "@medusajs/framework/utils" + * + * class MyPaymentProviderService extends AbstractPaymentProvider< + * Options + * > { + * async deleteAccountHolder({ context }: DeleteAccountHolderInput) { + * const { account_holder } = context + * const accountHolderId = account_holder?.data?.id as string | undefined + * if (!accountHolderId) { + * throw new MedusaError( + * MedusaError.Types.INVALID_DATA, + * "Missing account holder ID." + * ) + * } + * + * // assuming you have a client that deletes the account holder + * await this.client.deleteAccountHolder({ + * id: accountHolderId + * }) + * + * return {} + * } + * } + */ deleteAccountHolder?( data: DeleteAccountHolderInput ): Promise + /** + * This method is used to retrieve the list of saved payment methods for an account holder + * in the third-party payment provider. A payment provider that supports saving payment methods + * must implement this method. + * + * @param data - Input data including the details of the account holder to list payment methods for. + * @returns The list of payment methods saved for the account holder. If an error occurs, throw it. + * + * @example + * import { MedusaError } from "@medusajs/framework/utils" + * + * class MyPaymentProviderService extends AbstractPaymentProvider< + * Options + * > { + * async listPaymentMethods({ context }: ListPaymentMethodsInput) { + * const { account_holder } = context + * const accountHolderId = account_holder?.data?.id as string | undefined + * + * if (!accountHolderId) { + * throw new MedusaError( + * MedusaError.Types.INVALID_DATA, + * "Missing account holder ID." + * ) + * } + * + * // assuming you have a client that lists the payment methods + * const paymentMethods = await this.client.listPaymentMethods({ + * customer_id: accountHolderId + * }) + * + * return paymentMethods.map((pm) => ({ + * id: pm.id, + * data: pm as unknown as Record + * })) + * } + * } + */ listPaymentMethods?( data: ListPaymentMethodsInput ): Promise + /** + * This method is used to save a customer's payment method, such as a credit card, in the + * third-party payment provider. A payment provider that supports saving payment methods + * must implement this method. + * + * @param data - The details of the payment method to save. + * @returns The result of saving the payment method. If an error occurs, throw it. + * + * @example + * import { MedusaError } from "@medusajs/framework/utils" + * + * class MyPaymentProviderService extends AbstractPaymentProvider< + * Options + * > { + * async savePaymentMethod({ context, data }: SavePaymentMethodInput) { * + * const accountHolderId = context?.account_holder?.data?.id as + * | string + * | undefined + * + * if (!accountHolderId) { + * throw new MedusaError( + * MedusaError.Types.INVALID_DATA, + * "Missing account holder ID." + * ) + * } + * + * // assuming you have a client that saves the payment method + * const paymentMethod = await this.client.savePaymentMethod({ + * customer_id: accountHolderId, + * ...data + * }) + * + * return { + * id: paymentMethod.id, + * data: paymentMethod as unknown as Record + * } + * } + * } + */ savePaymentMethod?( data: SavePaymentMethodInput ): Promise