chore(): start moving some packages to the core directory (#7215)
This commit is contained in:
committed by
GitHub
parent
fdee748eed
commit
bbccd6481d
275
packages/core/utils/src/payment/abstract-payment-provider.ts
Normal file
275
packages/core/utils/src/payment/abstract-payment-provider.ts
Normal file
@@ -0,0 +1,275 @@
|
||||
import {
|
||||
CreatePaymentProviderSession,
|
||||
IPaymentProvider,
|
||||
MedusaContainer,
|
||||
PaymentProviderError,
|
||||
PaymentProviderSessionResponse,
|
||||
PaymentSessionStatus,
|
||||
ProviderWebhookPayload,
|
||||
UpdatePaymentProviderSession,
|
||||
WebhookActionResult
|
||||
} from "@medusajs/types"
|
||||
|
||||
/**
|
||||
* ## Overview
|
||||
*
|
||||
* A payment provider is used to handle and process payments, such as authorizing, capturing, and refund payments.
|
||||
*
|
||||
* Refer to [this guide](https://docs.medusajs.com/experimental/payment/payment-provider/) to learn more about payment providers.
|
||||
*
|
||||
* Refer to [this guide](https://docs.medusajs.com/experimental/payment/payment-flow/) to learn more about the payment flow.
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## How to Create a Payment Provider
|
||||
*
|
||||
* A payment provider is a TypeScript or JavaScript class that extends the `AbstractPaymentProvider` class imported from `@medusajsa/utils`.
|
||||
*
|
||||
* You can create the payment provider in a module or plugin, then pass that module/plugin in the Payment Module's `providers` option. You can also pass the path to the file
|
||||
* that defines the provider if it's created in the Medusa application's codebase.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* ```ts
|
||||
* abstract class MyPayment extends AbstractPaymentProvider<MyConfigurations> {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## Configuration Type Parameter
|
||||
*
|
||||
* The `AbstractPaymentProvider` class accepts an optional type parameter that defines the type of configuration that your payment provider expects.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* ```ts
|
||||
* interface MyConfigurations {
|
||||
* apiKey: string
|
||||
* }
|
||||
*
|
||||
* abstract class MyPayment extends AbstractPaymentProvider<MyConfigurations> {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## Identifier Property
|
||||
*
|
||||
* The `PaymentProvider` data model has 2 properties: `id` and `is_enabled`.
|
||||
*
|
||||
* ```ts
|
||||
* class MyPaymentProvider extends AbstractPaymentProvider<MyConfigurations> {
|
||||
* static identifier = "my-payment"
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## PROVIDER Property
|
||||
*
|
||||
* The `PROVIDER` static property is used when registering the provider in the dependency container. Typically, it would have the
|
||||
* same value as the `identifier` property.
|
||||
*
|
||||
* ```ts
|
||||
* class MyPaymentProvider extends AbstractPaymentProvider<MyConfigurations> {
|
||||
* static PROVIDER = "my-payment"
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## PaymentProviderError
|
||||
*
|
||||
* Before diving into the methods of the Payment Provider, you'll notice that part of the expected return signature of these method includes `PaymentProviderError`.
|
||||
*
|
||||
* ```ts
|
||||
* interface PaymentProviderError {
|
||||
* error: string
|
||||
* code?: string
|
||||
* detail?: any
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* While implementing the Payment Provider's methods, if you need to inform the Payment Module that an error occurred at a certain stage,
|
||||
* return an object having the attributes defined in the `PaymentProviderError` interface.
|
||||
*
|
||||
* For example, the Stripe payment provider has the following method to create the error object, which is used within other methods:
|
||||
*
|
||||
* ```ts
|
||||
* abstract class StripeBase extends AbstractPaymentProvider {
|
||||
* // ...
|
||||
* protected buildError(
|
||||
* message: string,
|
||||
* error: Stripe.StripeRawError | PaymentProviderError | Error
|
||||
* ): PaymentProviderError {
|
||||
* return {
|
||||
* error: message,
|
||||
* code: "code" in error ? error.code : "unknown",
|
||||
* detail: isPaymentProviderError(error)
|
||||
* ? `${error.error}${EOL}${error.detail ?? ""}`
|
||||
* : "detail" in error
|
||||
* ? error.detail
|
||||
* : error.message ?? "",
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // used in other methods
|
||||
* async retrievePayment(
|
||||
* paymentSessionData: Record<string, unknown>
|
||||
* ): Promise<
|
||||
* PaymentProviderError |
|
||||
* PaymentProviderSessionResponse["session_data"]
|
||||
* > {
|
||||
* try {
|
||||
* // ...
|
||||
* } catch (e) {
|
||||
* return this.buildError(
|
||||
* "An error occurred in retrievePayment",
|
||||
* e
|
||||
* )
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
|
||||
implements IPaymentProvider
|
||||
{
|
||||
/**
|
||||
* You can use the `constructor` of your Payment Provider to have access to resources in your application through the [dependency container](https://docs.medusajs.com/development/fundamentals/dependency-injection).
|
||||
*
|
||||
* You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs,
|
||||
* you can initialize it in the constructor and use it in other methods in the service.
|
||||
*
|
||||
* The payment provider also can access the configurations of the module or plugin it's created in as a second parameter.
|
||||
*
|
||||
* @param {MedusaContainer} container - An instance of `MedusaContainer` that allows you to access other resources in the [dependency container](https://docs.medusajs.com/development/fundamentals/dependency-injection)
|
||||
* @param {Record<string, unknown>} config - If this provider processor is created in a module or plugin, their options are passed in this parameter.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* class MyPaymentProvider extends AbstractPaymentProvider<MyConfigurations> {
|
||||
* // ...
|
||||
* constructor(container, config) {
|
||||
* super(container, config)
|
||||
* // you can access options here
|
||||
*
|
||||
* // you can also initialize a client that
|
||||
* // communicates with a third-party service.
|
||||
* this.client = new Client(options)
|
||||
* }
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
protected constructor(
|
||||
protected readonly container: MedusaContainer,
|
||||
protected readonly config: TConfig = {} as TConfig // eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static _isPaymentProvider = true
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static isPaymentProvider(object): boolean {
|
||||
return object?.constructor?._isPaymentProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* The `PaymentProvider` data model has 2 properties: `id` and `is_enabled`.
|
||||
*
|
||||
* ```ts
|
||||
* class MyPaymentProvider extends AbstractPaymentProvider<MyConfigurations> {
|
||||
* static identifier = "my-payment"
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public static identifier: string
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* Return a unique identifier to retrieve the payment plugin provider
|
||||
*/
|
||||
public getIdentifier(): string {
|
||||
const ctr = this.constructor as typeof AbstractPaymentProvider
|
||||
|
||||
if (!ctr.identifier) {
|
||||
throw new Error(`Missing static property "identifier".`)
|
||||
}
|
||||
|
||||
return ctr.identifier
|
||||
}
|
||||
|
||||
abstract capturePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
|
||||
abstract authorizePayment(
|
||||
paymentSessionData: Record<string, unknown>,
|
||||
context: Record<string, unknown>
|
||||
): Promise<
|
||||
| PaymentProviderError
|
||||
| {
|
||||
status: PaymentSessionStatus
|
||||
data: PaymentProviderSessionResponse["data"]
|
||||
}
|
||||
>
|
||||
|
||||
abstract cancelPayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
|
||||
abstract initiatePayment(
|
||||
context: CreatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
|
||||
abstract deletePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
|
||||
abstract getPaymentStatus(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentSessionStatus>
|
||||
|
||||
abstract refundPayment(
|
||||
paymentSessionData: Record<string, unknown>,
|
||||
refundAmount: number
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
|
||||
abstract retrievePayment(
|
||||
paymentSessionData: Record<string, unknown>
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
|
||||
|
||||
abstract updatePayment(
|
||||
context: UpdatePaymentProviderSession
|
||||
): Promise<PaymentProviderError | PaymentProviderSessionResponse>
|
||||
|
||||
abstract getWebhookActionAndData(
|
||||
data: ProviderWebhookPayload["payload"]
|
||||
): Promise<WebhookActionResult>
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
export function isPaymentProviderError(obj: any): obj is PaymentProviderError {
|
||||
return (
|
||||
obj &&
|
||||
typeof obj === "object" &&
|
||||
"error" in obj &&
|
||||
"code" in obj &&
|
||||
"detail" in obj
|
||||
)
|
||||
}
|
||||
4
packages/core/utils/src/payment/index.ts
Normal file
4
packages/core/utils/src/payment/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from "./abstract-payment-provider"
|
||||
export * from "./payment-collection"
|
||||
export * from "./payment-session"
|
||||
export * from "./webhook"
|
||||
27
packages/core/utils/src/payment/payment-collection.ts
Normal file
27
packages/core/utils/src/payment/payment-collection.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
* The payment collection's status.
|
||||
*/
|
||||
export enum PaymentCollectionStatus {
|
||||
/**
|
||||
* The payment collection isn't paid.
|
||||
*/
|
||||
NOT_PAID = "not_paid",
|
||||
/**
|
||||
* The payment collection is awaiting payment.
|
||||
*/
|
||||
AWAITING = "awaiting",
|
||||
/**
|
||||
* The payment collection is authorized.
|
||||
*/
|
||||
AUTHORIZED = "authorized",
|
||||
/**
|
||||
* Some of the payments in the payment collection are authorized.
|
||||
*/
|
||||
PARTIALLY_AUTHORIZED = "partially_authorized",
|
||||
/**
|
||||
* The payment collection is canceled.
|
||||
*/
|
||||
CANCELED = "canceled",
|
||||
}
|
||||
27
packages/core/utils/src/payment/payment-session.ts
Normal file
27
packages/core/utils/src/payment/payment-session.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
* The status of a payment session.
|
||||
*/
|
||||
export enum PaymentSessionStatus {
|
||||
/**
|
||||
* The payment is authorized.
|
||||
*/
|
||||
AUTHORIZED = "authorized",
|
||||
/**
|
||||
* The payment is pending.
|
||||
*/
|
||||
PENDING = "pending",
|
||||
/**
|
||||
* The payment requires an action.
|
||||
*/
|
||||
REQUIRES_MORE = "requires_more",
|
||||
/**
|
||||
* An error occurred while processing the payment.
|
||||
*/
|
||||
ERROR = "error",
|
||||
/**
|
||||
* The payment is canceled.
|
||||
*/
|
||||
CANCELED = "canceled",
|
||||
}
|
||||
25
packages/core/utils/src/payment/webhook.ts
Normal file
25
packages/core/utils/src/payment/webhook.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export enum PaymentWebhookEvents {
|
||||
WebhookReceived = "payment.webhook_received",
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalized events from payment provider to internal payment module events.
|
||||
*/
|
||||
export enum PaymentActions {
|
||||
/**
|
||||
* Payment session has been authorized and there are available funds for capture.
|
||||
*/
|
||||
AUTHORIZED = "authorized",
|
||||
/**
|
||||
* Payment was successful and the mount is captured.
|
||||
*/
|
||||
SUCCESSFUL = "captured",
|
||||
/**
|
||||
* Payment failed.
|
||||
*/
|
||||
FAILED = "failed",
|
||||
/**
|
||||
* Received an event that is not processable.
|
||||
*/
|
||||
NOT_SUPPORTED = "not_supported",
|
||||
}
|
||||
Reference in New Issue
Block a user