Skip to content

Commit

Permalink
fix: Address feedback on PR
Browse files Browse the repository at this point in the history
  • Loading branch information
sradevski committed Jan 21, 2025
1 parent 2d1a870 commit 69d6110
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 128 deletions.
4 changes: 2 additions & 2 deletions packages/core/types/src/payment/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,11 @@ export interface IPaymentProvider {
paymentSessionData: Record<string, unknown>
): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>

listPaymentMethods(
listPaymentMethods?(
context: PaymentProviderContext
): Promise<PaymentMethodResponse[]>

savePaymentMethod(
savePaymentMethod?(
input: SavePaymentMethod
): Promise<PaymentProviderError | SavePaymentMethodResponse>

Expand Down
103 changes: 0 additions & 103 deletions packages/core/utils/src/payment/abstract-payment-provider.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import {
CreatePaymentProviderSession,
IPaymentProvider,
PaymentMethodResponse,
PaymentProviderContext,
PaymentProviderError,
PaymentProviderSessionResponse,
PaymentSessionStatus,
ProviderWebhookPayload,
SavePaymentMethod,
SavePaymentMethodResponse,
UpdatePaymentProviderSession,
WebhookActionResult,
} from "@medusajs/types"
Expand Down Expand Up @@ -627,105 +623,6 @@ export abstract class AbstractPaymentProvider<TConfig = Record<string, unknown>>
context: UpdatePaymentProviderSession
): Promise<PaymentProviderError | PaymentProviderSessionResponse>

/**
* List the payment methods associated with the context (eg. customer) of the payment provider, if any.
*
* @param context - The context for which the payment methods are listed. Usually the customer should be provided.
* @returns An object whose `payment_methods` property is set to the data returned by the payment provider.
*
* @example
* // other imports...
* import {
* PaymentProviderContext,
* PaymentProviderError,
* PaymentMethodResponse
* PaymentProviderSessionResponse,
* } from "@medusajs/framework/types"
*
*
* class MyPaymentProviderService extends AbstractPaymentProvider<
* Options
* > {
* async listPaymentMethods(
* context: PaymentProviderContext
* ): Promise<PaymentMethodResponse> {
* const {
* customer,
* } = context
* const externalCustomerId = customer.metadata.stripe_id
*
* try {
* // assuming you have a client that updates the payment
* const response = await this.client.listPaymentMethods(
* {customer: externalCustomerId}
* )
*
* return response.map((method) => ({
* id: method.id,
* data: method
* }))
* } catch (e) {
* return {
* error: e,
* code: "unknown",
* detail: e
* }
* }
* }
*
* // ...
* }
*/
abstract listPaymentMethods(
context: PaymentProviderContext
): Promise<PaymentMethodResponse[]>

/**
* Saves a payment method associated with the context (eg. customer) of the payment provider.
*
* @param input -The data for the request and context for which the payment method is saved. Usually the customer should be provided.
* @returns An object whose `data` property is set to the data returned by the payment provider.
*
* @example
* // other imports...
* import {
* SavePaymentMethod,
* PaymentProviderError,
* SavePaymentMethodResponse
* } from "@medusajs/framework/types"
*
*
* class MyPaymentProviderService extends AbstractPaymentProvider<
* Options
* > {
* async savePaymentMethod(
* input: SavePaymentMethod
* ): Promise<PaymentProviderError | SavePaymentMethodResponse> {
* const {context, data } = input
* const externalCustomerId = context.customer.metadata.stripe_id
*
* if(!externalCustomerId) {
* return {
* error: new Error("Customer ID is required"),
* code: "unknown",
* detail: "Customer ID is required"
* }
* }
*
* const response = await this.client.savePaymentMethod(
* {customer: externalCustomerId, ...data}
* )
*
* return response
* }
*
* // ...
* }
*/
abstract savePaymentMethod(
input: SavePaymentMethod
): Promise<PaymentProviderError | SavePaymentMethodResponse>

/**
* This method is executed when a webhook event is received from the third-party payment provider. Use it
* to process the action of the payment provider.
Expand Down
12 changes: 0 additions & 12 deletions packages/modules/payment/src/providers/system.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import {
CreatePaymentProviderSession,
PaymentMethodResponse,
PaymentProviderError,
PaymentProviderSessionResponse,
ProviderWebhookPayload,
SavePaymentMethodResponse,
WebhookActionResult,
} from "@medusajs/framework/types"
import {
Expand Down Expand Up @@ -74,16 +72,6 @@ export class SystemProviderService extends AbstractPaymentProvider {
return {}
}

async listPaymentMethods(_): Promise<PaymentMethodResponse[]> {
return []
}

async savePaymentMethod(
_
): Promise<PaymentProviderError | SavePaymentMethodResponse> {
return { id: "", data: {} }
}

async getWebhookActionAndData(
data: ProviderWebhookPayload["payload"]
): Promise<WebhookActionResult> {
Expand Down
25 changes: 18 additions & 7 deletions packages/modules/payment/src/services/payment-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,10 @@ export default class PaymentModuleService
filters.context
)

if (!res) {
return []
}

return res.map((item) => ({
id: item.id,
data: item.data,
Expand All @@ -939,6 +943,10 @@ export default class PaymentModuleService
filters.context
)

if (!paymentMethods) {
return [[], 0]
}

const normalizedResponse = paymentMethods.map((item) => ({
id: item.id,
data: item.data,
Expand All @@ -965,17 +973,20 @@ export default class PaymentModuleService
): Promise<PaymentMethodDTO | PaymentMethodDTO[]> {
const input = Array.isArray(data) ? data : [data]

const result = await Promise.all(
const result = await promiseAll(
input.map((item) =>
this.paymentProviderService_.savePaymentMethod(item.provider_id, item)
)
),
{ aggregateErrors: true }
)

const normalizedResponse = result.map((item, i) => ({
id: item.id,
data: item.data,
provider_id: input[i].provider_id,
}))
const normalizedResponse = result
.map((item, i) => ({
id: item?.id,
data: item?.data,
provider_id: input[i].provider_id,
}))
.filter((item) => !!item.id && !!item.data) as PaymentMethodDTO[]

return Array.isArray(data) ? normalizedResponse : normalizedResponse[0]
}
Expand Down
8 changes: 4 additions & 4 deletions packages/modules/payment/src/services/payment-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,17 @@ Please make sure that the provider is registered in the container and it is conf
async listPaymentMethods(
providerId: string,
context: PaymentProviderContext
): Promise<PaymentMethodResponse[]> {
): Promise<PaymentMethodResponse[] | undefined> {
const provider = this.retrieveProvider(providerId)
return await provider.listPaymentMethods(context)
return await provider.listPaymentMethods?.(context)
}

async savePaymentMethod(
providerId: string,
input: SavePaymentMethod
): Promise<SavePaymentMethodResponse> {
): Promise<SavePaymentMethodResponse | undefined> {
const provider = this.retrieveProvider(providerId)
const res = await provider.savePaymentMethod(input)
const res = await provider.savePaymentMethod?.(input)

if (isPaymentProviderError(res)) {
this.throwPaymentProviderError(res)
Expand Down

0 comments on commit 69d6110

Please sign in to comment.