feat(medusa, stripe, paypal): Add update payment session support to the abstract payment processor API (#4442)

* feat(medusa, stripe, paypal): Add update payment session support to the abstract payment processor API

* continue to add updatePaymentData

* feat: Add update payment data to paypal as well and add stripe tests

* fix stripe updatePaymentData returned object type

* fix tests

* Create three-ravens-raise.md

* fix paypal updatePayment data impl

---------

Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Adrien de PerettiandOliver Windall Juhl authored and GitHub committed 2023-07-10 15:59:19 +02:00
1 parent 1903217705
commit 4264302f21
9 files changed
+345 -138

No files matched your search

@@ -2,6 +2,7 @@ import {
EXISTING_CUSTOMER_EMAIL,
FAIL_INTENT_ID,
PARTIALLY_FAIL_INTENT_ID,
STRIPE_ID,
WRONG_CUSTOMER_EMAIL,
} from "../../__mocks__/stripe"
import { PaymentIntentDataByStatus } from "../../__fixtures__/data"
@@ -212,3 +213,13 @@ export const updatePaymentContextFailWithDifferentAmount = {
amount: 1000,
},
}
export const updatePaymentDataWithAmountData = {
sessionId: STRIPE_ID,
amount: 2000,
}
export const updatePaymentDataWithoutAmountData = {
sessionId: STRIPE_ID,
customProp: "test",
}
@@ -26,6 +26,8 @@ import {
updatePaymentContextWithExistingCustomer,
updatePaymentContextWithExistingCustomerStripeId,
updatePaymentContextWithWrongEmail,
updatePaymentDataWithAmountData,
updatePaymentDataWithoutAmountData,
} from "../__fixtures__/data"
import {
PARTIALLY_FAIL_INTENT_ID,
@@ -571,4 +573,53 @@ describe("StripeTest", () => {
})
})
})
describe("updatePaymentData", function () {
let stripeTest
beforeAll(async () => {
const scopedContainer = { ...container }
stripeTest = new StripeTest(scopedContainer, { api_key: "test" })
})
beforeEach(() => {
jest.clearAllMocks()
})
it("should succeed to update the payment data", async () => {
const result = await stripeTest.updatePaymentData(
updatePaymentDataWithoutAmountData.sessionId,
{ ...updatePaymentDataWithoutAmountData, sessionId: undefined }
)
expect(StripeMock.paymentIntents.update).toHaveBeenCalled()
expect(StripeMock.paymentIntents.update).toHaveBeenCalledWith(
updatePaymentDataWithoutAmountData.sessionId,
{
customProp: updatePaymentDataWithoutAmountData.customProp,
}
)
expect(result).toEqual(
expect.objectContaining({
customProp: updatePaymentDataWithoutAmountData.customProp,
})
)
})
it("should fail to update the payment data if the amount is present", async () => {
const result = await stripeTest.updatePaymentData(
updatePaymentDataWithAmountData.sessionId,
{ ...updatePaymentDataWithAmountData, sessionId: undefined }
)
expect(StripeMock.paymentIntents.update).not.toHaveBeenCalled()
expect(result).toEqual({
error: "An error occurred in updatePaymentData",
code: undefined,
detail: "Cannot update amount, use updatePayment instead",
})
})
})
})
@@ -14,6 +14,7 @@ import {
PaymentIntentOptions,
StripeOptions,
} from "../types"
import { MedusaError } from "@medusajs/utils"
abstract class StripeBase extends AbstractPaymentProcessor {
static identifier = ""
@@ -281,6 +282,25 @@ abstract class StripeBase extends AbstractPaymentProcessor {
}
}
async updatePaymentData(sessionId: string, data: Record<string, unknown>) {
try {
// Prevent from updating the amount from here as it should go through
// the updatePayment method to perform the correct logic
if (data.amount) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Cannot update amount, use updatePayment instead"
)
}
return (await this.stripe_.paymentIntents.update(sessionId, {
...data,
})) as unknown as PaymentProcessorSessionResponse["session_data"]
} catch (e) {
return this.buildError("An error occurred in updatePaymentData", e)
}
}
/**
* Constructs Stripe Webhook event
* @param {object} data - the data of the webhook request: req.body