fix(payment): Capture payment (#9469)

What
- Add missing `captured_at` field to payment retrieval
- Properly delete Medusa captures in case 3rd party capture call fails
This commit is contained in:
Oli Juhl authored and GitHub committed 2024-10-04 15:15:10 +00:00
1 parent eea2bfdef1
commit 67e08dc989
3 files changed
+120 -26

No files matched your search

@@ -636,21 +636,28 @@ moduleIntegrationTestRunner<IPaymentModuleService>({
)
})
it("should fail to capture already captured payment", async () => {
it("should return payment if payment is already captured", async () => {
await service.capturePayment({
amount: 100,
payment_id: "pay-id-1",
})
const error = await service
.capturePayment({
amount: 100,
payment_id: "pay-id-1",
})
.catch((e) => e)
const capturedPayment = await service.capturePayment({
amount: 100,
payment_id: "pay-id-1",
})
expect(error.message).toEqual(
"You cannot capture more than the authorized amount substracted by what is already captured."
expect(capturedPayment).toEqual(
expect.objectContaining({
id: "pay-id-1",
amount: 100,
captures: [
expect.objectContaining({
amount: 100,
}),
],
captured_at: expect.any(Date),
})
)
})
@@ -583,7 +583,7 @@ export default class PaymentModuleService
data: CreateCaptureDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<PaymentDTO> {
const [payment, isFullyCaptured] = await this.capturePayment_(
const { payment, isFullyCaptured, capture } = await this.capturePayment_(
data,
sharedContext
)
@@ -595,7 +595,9 @@ export default class PaymentModuleService
sharedContext
)
} catch (error) {
await super.deleteCaptures(data.payment_id, sharedContext)
if (capture?.id) {
await super.deleteCaptures({ id: capture.id }, sharedContext)
}
throw error
}
@@ -615,7 +617,11 @@ export default class PaymentModuleService
private async capturePayment_(
data: CreateCaptureDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<[Payment, boolean]> {
): Promise<{
payment: Payment
isFullyCaptured: boolean
capture?: Capture
}> {
const payment = await this.paymentService_.retrieve(
data.payment_id,
{
@@ -626,6 +632,7 @@ export default class PaymentModuleService
"payment_collection_id",
"amount",
"raw_amount",
"captured_at",
"canceled_at",
],
relations: ["captures.raw_amount"],
@@ -646,14 +653,7 @@ export default class PaymentModuleService
}
if (payment.captured_at) {
return [
(await this.retrievePayment(
data.payment_id,
{ relations: ["captures"] },
sharedContext
)) as unknown as Payment,
true,
]
return { payment, isFullyCaptured: true }
}
const capturedAmount = payment.captures.reduce((captureAmount, next) => {
@@ -677,7 +677,7 @@ export default class PaymentModuleService
)
const isFullyCaptured = MathBN.gte(totalCaptured, authorizedAmount)
await this.captureService_.create(
const capture = await this.captureService_.create(
{
payment: data.payment_id,
amount: data.amount,
@@ -686,7 +686,7 @@ export default class PaymentModuleService
sharedContext
)
return [payment, isFullyCaptured]
return { payment, isFullyCaptured, capture }
}
@InjectManager()
private async capturePaymentFromProvider_(