|
|
|
@@ -1,8 +1,11 @@
|
|
|
|
|
import {
|
|
|
|
|
CaptureDTO,
|
|
|
|
|
Context,
|
|
|
|
|
CreateCaptureDTO,
|
|
|
|
|
CreatePaymentCollectionDTO,
|
|
|
|
|
CreatePaymentDTO,
|
|
|
|
|
CreatePaymentSessionDTO,
|
|
|
|
|
CreateRefundDTO,
|
|
|
|
|
DAL,
|
|
|
|
|
InternalModuleDeclaration,
|
|
|
|
|
IPaymentModuleService,
|
|
|
|
@@ -10,6 +13,8 @@ import {
|
|
|
|
|
ModulesSdkTypes,
|
|
|
|
|
PaymentCollectionDTO,
|
|
|
|
|
PaymentDTO,
|
|
|
|
|
PaymentSessionDTO,
|
|
|
|
|
RefundDTO,
|
|
|
|
|
SetPaymentSessionsDTO,
|
|
|
|
|
UpdatePaymentCollectionDTO,
|
|
|
|
|
UpdatePaymentDTO,
|
|
|
|
@@ -18,6 +23,8 @@ import {
|
|
|
|
|
InjectTransactionManager,
|
|
|
|
|
MedusaContext,
|
|
|
|
|
ModulesSdkUtils,
|
|
|
|
|
MedusaError,
|
|
|
|
|
InjectManager,
|
|
|
|
|
} from "@medusajs/utils"
|
|
|
|
|
|
|
|
|
|
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
|
|
|
@@ -25,49 +32,58 @@ import {
|
|
|
|
|
Capture,
|
|
|
|
|
Payment,
|
|
|
|
|
PaymentCollection,
|
|
|
|
|
PaymentMethodToken,
|
|
|
|
|
PaymentProvider,
|
|
|
|
|
PaymentSession,
|
|
|
|
|
Refund,
|
|
|
|
|
} from "@models"
|
|
|
|
|
|
|
|
|
|
type InjectedDependencies = {
|
|
|
|
|
baseRepository: DAL.RepositoryService
|
|
|
|
|
paymentService: ModulesSdkTypes.InternalModuleService<any>
|
|
|
|
|
captureService: ModulesSdkTypes.InternalModuleService<any>
|
|
|
|
|
refundService: ModulesSdkTypes.InternalModuleService<any>
|
|
|
|
|
paymentSessionService: ModulesSdkTypes.InternalModuleService<any>
|
|
|
|
|
paymentCollectionService: ModulesSdkTypes.InternalModuleService<any>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const generateMethodForModels = [
|
|
|
|
|
Capture,
|
|
|
|
|
PaymentCollection,
|
|
|
|
|
PaymentMethodToken,
|
|
|
|
|
PaymentProvider,
|
|
|
|
|
PaymentSession,
|
|
|
|
|
Refund,
|
|
|
|
|
]
|
|
|
|
|
const generateMethodForModels = [PaymentCollection, PaymentSession]
|
|
|
|
|
|
|
|
|
|
export default class PaymentModuleService<
|
|
|
|
|
TPaymentCollection extends PaymentCollection = PaymentCollection
|
|
|
|
|
TPaymentCollection extends PaymentCollection = PaymentCollection,
|
|
|
|
|
TPayment extends Payment = Payment,
|
|
|
|
|
TCapture extends Capture = Capture,
|
|
|
|
|
TRefund extends Refund = Refund,
|
|
|
|
|
TPaymentSession extends PaymentSession = PaymentSession
|
|
|
|
|
>
|
|
|
|
|
extends ModulesSdkUtils.abstractModuleServiceFactory<
|
|
|
|
|
// TODO revisit when moving forward frane
|
|
|
|
|
InjectedDependencies,
|
|
|
|
|
PaymentDTO,
|
|
|
|
|
PaymentCollectionDTO,
|
|
|
|
|
{
|
|
|
|
|
Capture: { dto: any }
|
|
|
|
|
PaymentCollection: { dto: any }
|
|
|
|
|
PaymentMethodToken: { dto: any }
|
|
|
|
|
PaymentProvider: { dto: any }
|
|
|
|
|
PaymentSession: { dto: any }
|
|
|
|
|
Refund: { dto: any }
|
|
|
|
|
PaymentCollection: { dto: PaymentCollectionDTO }
|
|
|
|
|
PaymentSession: { dto: PaymentSessionDTO }
|
|
|
|
|
Payment: { dto: PaymentDTO }
|
|
|
|
|
Capture: { dto: CaptureDTO }
|
|
|
|
|
Refund: { dto: RefundDTO }
|
|
|
|
|
}
|
|
|
|
|
>(Payment, generateMethodForModels, entityNameToLinkableKeysMap)
|
|
|
|
|
>(PaymentCollection, generateMethodForModels, entityNameToLinkableKeysMap)
|
|
|
|
|
implements IPaymentModuleService
|
|
|
|
|
{
|
|
|
|
|
protected baseRepository_: DAL.RepositoryService
|
|
|
|
|
|
|
|
|
|
protected paymentService_: ModulesSdkTypes.InternalModuleService<TPayment>
|
|
|
|
|
protected captureService_: ModulesSdkTypes.InternalModuleService<TCapture>
|
|
|
|
|
protected refundService_: ModulesSdkTypes.InternalModuleService<TRefund>
|
|
|
|
|
protected paymentSessionService_: ModulesSdkTypes.InternalModuleService<TPaymentSession>
|
|
|
|
|
protected paymentCollectionService_: ModulesSdkTypes.InternalModuleService<TPaymentCollection>
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
{ baseRepository, paymentCollectionService }: InjectedDependencies,
|
|
|
|
|
{
|
|
|
|
|
baseRepository,
|
|
|
|
|
paymentService,
|
|
|
|
|
captureService,
|
|
|
|
|
refundService,
|
|
|
|
|
paymentSessionService,
|
|
|
|
|
paymentCollectionService,
|
|
|
|
|
}: InjectedDependencies,
|
|
|
|
|
protected readonly moduleDeclaration: InternalModuleDeclaration
|
|
|
|
|
) {
|
|
|
|
|
// @ts-ignore
|
|
|
|
@@ -75,6 +91,10 @@ export default class PaymentModuleService<
|
|
|
|
|
|
|
|
|
|
this.baseRepository_ = baseRepository
|
|
|
|
|
|
|
|
|
|
this.refundService_ = refundService
|
|
|
|
|
this.captureService_ = captureService
|
|
|
|
|
this.paymentService_ = paymentService
|
|
|
|
|
this.paymentSessionService_ = paymentSessionService
|
|
|
|
|
this.paymentCollectionService_ = paymentCollectionService
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -140,6 +160,256 @@ export default class PaymentModuleService<
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createPayment(
|
|
|
|
|
data: CreatePaymentDTO,
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO>
|
|
|
|
|
createPayment(
|
|
|
|
|
data: CreatePaymentDTO[],
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO[]>
|
|
|
|
|
|
|
|
|
|
@InjectTransactionManager("baseRepository_")
|
|
|
|
|
async createPayment(
|
|
|
|
|
data: CreatePaymentDTO | CreatePaymentDTO[],
|
|
|
|
|
@MedusaContext() sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO | PaymentDTO[]> {
|
|
|
|
|
let input = Array.isArray(data) ? data : [data]
|
|
|
|
|
|
|
|
|
|
input = input.map((inputData) => ({
|
|
|
|
|
payment_collection: inputData.payment_collection_id,
|
|
|
|
|
payment_session: inputData.payment_session_id,
|
|
|
|
|
...inputData,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
const payments = await this.paymentService_.create(input, sharedContext)
|
|
|
|
|
|
|
|
|
|
return await this.baseRepository_.serialize<PaymentDTO[]>(
|
|
|
|
|
Array.isArray(data) ? payments : payments[0],
|
|
|
|
|
{
|
|
|
|
|
populate: true,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updatePayment(
|
|
|
|
|
data: UpdatePaymentDTO,
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentDTO>
|
|
|
|
|
updatePayment(
|
|
|
|
|
data: UpdatePaymentDTO[],
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentDTO[]>
|
|
|
|
|
|
|
|
|
|
@InjectTransactionManager("baseRepository_")
|
|
|
|
|
async updatePayment(
|
|
|
|
|
data: UpdatePaymentDTO | UpdatePaymentDTO[],
|
|
|
|
|
@MedusaContext() sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO | PaymentDTO[]> {
|
|
|
|
|
const input = Array.isArray(data) ? data : [data]
|
|
|
|
|
const result = await this.paymentService_.update(input, sharedContext)
|
|
|
|
|
|
|
|
|
|
return await this.baseRepository_.serialize<PaymentDTO[]>(
|
|
|
|
|
Array.isArray(data) ? result : result[0],
|
|
|
|
|
{
|
|
|
|
|
populate: true,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
capturePayment(
|
|
|
|
|
data: CreateCaptureDTO,
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO>
|
|
|
|
|
capturePayment(
|
|
|
|
|
data: CreateCaptureDTO[],
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO[]>
|
|
|
|
|
|
|
|
|
|
@InjectManager("baseRepository_")
|
|
|
|
|
async capturePayment(
|
|
|
|
|
data: CreateCaptureDTO | CreateCaptureDTO[],
|
|
|
|
|
@MedusaContext() sharedContext: Context = {}
|
|
|
|
|
): Promise<PaymentDTO | PaymentDTO[]> {
|
|
|
|
|
const input = Array.isArray(data) ? data : [data]
|
|
|
|
|
|
|
|
|
|
const payments = await this.capturePaymentBulk_(input, sharedContext)
|
|
|
|
|
|
|
|
|
|
return await this.baseRepository_.serialize(
|
|
|
|
|
Array.isArray(data) ? payments : payments[0],
|
|
|
|
|
{ populate: true }
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@InjectTransactionManager("baseRepository_")
|
|
|
|
|
protected async capturePaymentBulk_(
|
|
|
|
|
data: CreateCaptureDTO[],
|
|
|
|
|
@MedusaContext() sharedContext?: Context
|
|
|
|
|
): Promise<Payment[]> {
|
|
|
|
|
let payments = await this.paymentService_.list(
|
|
|
|
|
{ id: data.map((d) => d.payment_id) },
|
|
|
|
|
{},
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
const inputMap = new Map(data.map((d) => [d.payment_id, d]))
|
|
|
|
|
|
|
|
|
|
for (const payment of payments) {
|
|
|
|
|
const input = inputMap.get(payment.id)!
|
|
|
|
|
|
|
|
|
|
if (payment.captured_at) {
|
|
|
|
|
throw new MedusaError(
|
|
|
|
|
MedusaError.Types.INVALID_DATA,
|
|
|
|
|
"The payment is already fully captured."
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: revisit when https://github.com/medusajs/medusa/pull/6253 is merged
|
|
|
|
|
// if (payment.captured_amount + input.amount > payment.authorized_amount) {
|
|
|
|
|
// throw new MedusaError(
|
|
|
|
|
// MedusaError.Types.INVALID_DATA,
|
|
|
|
|
// `Total captured amount for payment: ${payment.id} exceeds authorized amount.`
|
|
|
|
|
// )
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await this.captureService_.create(
|
|
|
|
|
data.map((d) => ({
|
|
|
|
|
payment: d.payment_id,
|
|
|
|
|
amount: d.amount,
|
|
|
|
|
captured_by: d.captured_by,
|
|
|
|
|
})),
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
let fullyCapturedPaymentsId: string[] = []
|
|
|
|
|
for (const payment of payments) {
|
|
|
|
|
const input = inputMap.get(payment.id)!
|
|
|
|
|
|
|
|
|
|
// TODO: revisit when https://github.com/medusajs/medusa/pull/6253 is merged
|
|
|
|
|
// if (payment.captured_amount + input.amount === payment.amount) {
|
|
|
|
|
// fullyCapturedPaymentsId.push(payment.id)
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fullyCapturedPaymentsId.length) {
|
|
|
|
|
await this.paymentService_.update(
|
|
|
|
|
fullyCapturedPaymentsId.map((id) => ({ id, captured_at: new Date() })),
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: set PaymentCollection status if fully captured
|
|
|
|
|
|
|
|
|
|
return await this.paymentService_.list(
|
|
|
|
|
{ id: data.map((d) => d.payment_id) },
|
|
|
|
|
{
|
|
|
|
|
relations: ["captures"],
|
|
|
|
|
},
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
refundPayment(
|
|
|
|
|
data: CreateRefundDTO,
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO>
|
|
|
|
|
refundPayment(
|
|
|
|
|
data: CreateRefundDTO[],
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO[]>
|
|
|
|
|
|
|
|
|
|
@InjectManager("baseRepository_")
|
|
|
|
|
async refundPayment(
|
|
|
|
|
data: CreateRefundDTO | CreateRefundDTO[],
|
|
|
|
|
@MedusaContext() sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO | PaymentDTO[]> {
|
|
|
|
|
const input = Array.isArray(data) ? data : [data]
|
|
|
|
|
|
|
|
|
|
const payments = await this.refundPaymentBulk_(input, sharedContext)
|
|
|
|
|
|
|
|
|
|
return await this.baseRepository_.serialize(
|
|
|
|
|
Array.isArray(data) ? payments : payments[0],
|
|
|
|
|
{ populate: true }
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@InjectTransactionManager("baseRepository_")
|
|
|
|
|
async refundPaymentBulk_(
|
|
|
|
|
data: CreateRefundDTO[],
|
|
|
|
|
@MedusaContext() sharedContext?: Context
|
|
|
|
|
): Promise<Payment[]> {
|
|
|
|
|
const payments = await this.paymentService_.list(
|
|
|
|
|
{ id: data.map(({ payment_id }) => payment_id) },
|
|
|
|
|
{},
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const inputMap = new Map(data.map((d) => [d.payment_id, d]))
|
|
|
|
|
|
|
|
|
|
// TODO: revisit when https://github.com/medusajs/medusa/pull/6253 is merged
|
|
|
|
|
// for (const payment of payments) {
|
|
|
|
|
// const input = inputMap.get(payment.id)!
|
|
|
|
|
// if (payment.captured_amount < input.amount) {
|
|
|
|
|
// throw new MedusaError(
|
|
|
|
|
// MedusaError.Types.INVALID_DATA,
|
|
|
|
|
// `Refund amount for payment: ${payment.id} cannot be greater than the amount captured on the payment.`
|
|
|
|
|
// )
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
await this.refundService_.create(
|
|
|
|
|
data.map((d) => ({
|
|
|
|
|
payment: d.payment_id,
|
|
|
|
|
amount: d.amount,
|
|
|
|
|
captured_by: d.created_by,
|
|
|
|
|
})),
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return await this.paymentService_.list(
|
|
|
|
|
{ id: data.map(({ payment_id }) => payment_id) },
|
|
|
|
|
{
|
|
|
|
|
relations: ["refunds"],
|
|
|
|
|
},
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createPaymentSession(
|
|
|
|
|
paymentCollectionId: string,
|
|
|
|
|
data: CreatePaymentSessionDTO,
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentCollectionDTO>
|
|
|
|
|
createPaymentSession(
|
|
|
|
|
paymentCollectionId: string,
|
|
|
|
|
data: CreatePaymentSessionDTO[],
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentCollectionDTO>
|
|
|
|
|
|
|
|
|
|
@InjectTransactionManager("baseRepository_")
|
|
|
|
|
async createPaymentSession(
|
|
|
|
|
paymentCollectionId: string,
|
|
|
|
|
data: CreatePaymentSessionDTO | CreatePaymentSessionDTO[],
|
|
|
|
|
@MedusaContext() sharedContext?: Context
|
|
|
|
|
): Promise<PaymentCollectionDTO> {
|
|
|
|
|
let input = Array.isArray(data) ? data : [data]
|
|
|
|
|
|
|
|
|
|
input = input.map((inputData) => ({
|
|
|
|
|
payment_collection: paymentCollectionId,
|
|
|
|
|
...inputData,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
await this.paymentSessionService_.create(input, sharedContext)
|
|
|
|
|
|
|
|
|
|
return await this.retrievePaymentCollection(
|
|
|
|
|
paymentCollectionId,
|
|
|
|
|
{
|
|
|
|
|
relations: ["payment_sessions"],
|
|
|
|
|
},
|
|
|
|
|
sharedContext
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* TODO
|
|
|
|
|
*/
|
|
|
|
@@ -156,56 +426,20 @@ export default class PaymentModuleService<
|
|
|
|
|
): Promise<PaymentCollectionDTO> {
|
|
|
|
|
throw new Error("Method not implemented.")
|
|
|
|
|
}
|
|
|
|
|
createPayment(data: CreatePaymentDTO): Promise<PaymentDTO>
|
|
|
|
|
createPayment(data: CreatePaymentDTO[]): Promise<PaymentDTO[]>
|
|
|
|
|
createPayment(data: unknown): Promise<PaymentDTO | PaymentDTO[]> {
|
|
|
|
|
throw new Error("Method not implemented.")
|
|
|
|
|
}
|
|
|
|
|
capturePayment(
|
|
|
|
|
paymentId: string,
|
|
|
|
|
amount: number,
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentDTO> {
|
|
|
|
|
throw new Error("Method not implemented.")
|
|
|
|
|
}
|
|
|
|
|
refundPayment(
|
|
|
|
|
paymentId: string,
|
|
|
|
|
amount: number,
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentDTO> {
|
|
|
|
|
throw new Error("Method not implemented.")
|
|
|
|
|
}
|
|
|
|
|
updatePayment(
|
|
|
|
|
data: UpdatePaymentDTO,
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentDTO>
|
|
|
|
|
updatePayment(
|
|
|
|
|
data: UpdatePaymentDTO[],
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
|
|
|
|
|
cancelPayment(paymentId: string, sharedContext?: Context): Promise<PaymentDTO>
|
|
|
|
|
cancelPayment(
|
|
|
|
|
paymentId: string[],
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO[]>
|
|
|
|
|
updatePayment(
|
|
|
|
|
data: unknown,
|
|
|
|
|
sharedContext?: unknown
|
|
|
|
|
|
|
|
|
|
cancelPayment(
|
|
|
|
|
paymentId: string | string[],
|
|
|
|
|
sharedContext?: Context
|
|
|
|
|
): Promise<PaymentDTO | PaymentDTO[]> {
|
|
|
|
|
throw new Error("Method not implemented.")
|
|
|
|
|
}
|
|
|
|
|
createPaymentSession(
|
|
|
|
|
paymentCollectionId: string,
|
|
|
|
|
data: CreatePaymentSessionDTO,
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentCollectionDTO>
|
|
|
|
|
createPaymentSession(
|
|
|
|
|
paymentCollectionId: string,
|
|
|
|
|
data: CreatePaymentSessionDTO[],
|
|
|
|
|
sharedContext?: Context | undefined
|
|
|
|
|
): Promise<PaymentCollectionDTO>
|
|
|
|
|
createPaymentSession(
|
|
|
|
|
paymentCollectionId: unknown,
|
|
|
|
|
data: unknown,
|
|
|
|
|
sharedContext?: unknown
|
|
|
|
|
): Promise<PaymentCollectionDTO> {
|
|
|
|
|
throw new Error("Method not implemented.")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
authorizePaymentSessions(
|
|
|
|
|
paymentCollectionId: string,
|
|
|
|
|
sessionIds: string[],
|
|
|
|
|