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 Peretti
2023-07-10 15:59:19 +02:00
committed by GitHub
co-authored by Oliver Windall Juhl
parent 1903217705
commit 4264302f21
9 changed files with 345 additions and 138 deletions
+7
View File
@@ -0,0 +1,7 @@
---
"@medusajs/medusa": patch
"medusa-payment-paypal": patch
"medusa-payment-stripe": patch
---
feat(medusa, stripe, paypal): Add update payment session support to the abstract payment processor API
@@ -17,6 +17,7 @@ import { humanizeAmount } from "medusa-core-utils"
import { roundToTwo } from "./utils/utils"
import { CreateOrder, PaypalSdk } from "../core"
import { Logger } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
class PayPalProviderService extends AbstractPaymentProcessor {
static identifier = "paypal"
@@ -280,6 +281,23 @@ class PayPalProviderService 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 data
} catch (e) {
return this.buildError("An error occurred in updatePaymentData", e)
}
}
async retrieveOrderFromAuth(authorization) {
const link = authorization.links.find((l) => l.rel === "up")
const parts = link.href.split("/")
@@ -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
@@ -119,6 +119,16 @@ export interface PaymentProcessor {
getPaymentStatus(
paymentSessionData: Record<string, unknown>
): Promise<PaymentSessionStatus>
/**
* Update the session data for a payment session
*/
updatePaymentData(
sessionId: string,
data: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
>
}
/**
@@ -195,6 +205,13 @@ export abstract class AbstractPaymentProcessor implements PaymentProcessor {
abstract updatePayment(
context: PaymentProcessorContext
): Promise<PaymentProcessorError | PaymentProcessorSessionResponse | void>
abstract updatePaymentData(
sessionId: string,
data: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
>
}
/**
@@ -1,35 +1,44 @@
import { asClass, asFunction, asValue, createContainer } from "awilix"
import { MockManager, MockRepository } from "medusa-test-utils"
import PaymentProviderService from "../payment-provider";
import { PaymentProviderServiceMock } from "../__mocks__/payment-provider";
import { CustomerServiceMock } from "../__mocks__/customer";
import { FlagRouter } from "../../utils/flag-router";
import Logger from "../../loaders/logger";
import PaymentProviderService from "../payment-provider"
import { PaymentProviderServiceMock } from "../__mocks__/payment-provider"
import { CustomerServiceMock } from "../__mocks__/customer"
import { FlagRouter } from "../../utils/flag-router"
import Logger from "../../loaders/logger"
import {
AbstractPaymentProcessor,
PaymentProcessorContext,
PaymentProcessorError,
PaymentProcessorSessionResponse
} from "../../interfaces";
import { PaymentSessionStatus } from "../../models";
import { PaymentServiceMock } from "../__mocks__/payment";
PaymentProcessorSessionResponse,
} from "../../interfaces"
import { PaymentSessionStatus } from "../../models"
import { PaymentServiceMock } from "../__mocks__/payment"
export const defaultContainer = createContainer()
defaultContainer.register("paymentProviderService", asClass(PaymentProviderService))
defaultContainer.register(
"paymentProviderService",
asClass(PaymentProviderService)
)
defaultContainer.register("paymentService", asValue(PaymentServiceMock))
defaultContainer.register("manager", asValue(MockManager))
defaultContainer.register("paymentSessionRepository", asValue(MockRepository()))
defaultContainer.register("paymentProviderRepository", asValue(PaymentProviderServiceMock))
defaultContainer.register(
"paymentProviderRepository",
asValue(PaymentProviderServiceMock)
)
defaultContainer.register("paymentRepository", asValue(MockRepository()))
defaultContainer.register("refundRepository", asValue(MockRepository()))
defaultContainer.register("customerService", asValue(CustomerServiceMock))
defaultContainer.register("featureFlagRouter", asValue(new FlagRouter({})))
defaultContainer.register("logger", asValue(Logger))
defaultContainer.register("pp_payment_processor", asFunction((cradle) => new PaymentProcessor(cradle)))
defaultContainer.register(
"pp_payment_processor",
asFunction((cradle) => new PaymentProcessor(cradle))
)
export class PaymentProcessor extends AbstractPaymentProcessor {
constructor(container) {
super(container);
super(container)
}
authorizePayment(context: PaymentProcessorContext): Promise<
| PaymentProcessorError
@@ -38,43 +47,78 @@ export class PaymentProcessor extends AbstractPaymentProcessor {
data: PaymentProcessorSessionResponse["session_data"]
}
> {
return Promise.resolve({ } as any);
return Promise.resolve({} as any)
}
getPaymentStatus(paymentSessionData: Record<string, unknown>): Promise<PaymentSessionStatus> {
return Promise.resolve(PaymentSessionStatus.PENDING);
getPaymentStatus(
paymentSessionData: Record<string, unknown>
): Promise<PaymentSessionStatus> {
return Promise.resolve(PaymentSessionStatus.PENDING)
}
init(): Promise<void> {
return Promise.resolve(undefined);
return Promise.resolve(undefined)
}
initiatePayment(context: PaymentProcessorContext): Promise<PaymentProcessorError | PaymentProcessorSessionResponse> {
return Promise.resolve({ } as PaymentProcessorSessionResponse);
initiatePayment(
context: PaymentProcessorContext
): Promise<PaymentProcessorError | PaymentProcessorSessionResponse> {
return Promise.resolve({} as PaymentProcessorSessionResponse)
}
retrievePayment(paymentSessionData: Record<string, unknown>): Promise<PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]> {
return Promise.resolve({ });
retrievePayment(
paymentSessionData: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
> {
return Promise.resolve({})
}
updatePayment(context: PaymentProcessorContext): Promise<PaymentProcessorError | void> {
return Promise.resolve(undefined);
updatePayment(
context: PaymentProcessorContext
): Promise<PaymentProcessorError | void> {
return Promise.resolve(undefined)
}
capturePayment(paymentSessionData: Record<string, unknown>): Promise<PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]> {
return Promise.resolve({ });
capturePayment(
paymentSessionData: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
> {
return Promise.resolve({})
}
refundPayment(paymentSessionData: Record<string, unknown>): Promise<PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]> {
return Promise.resolve({});
refundPayment(
paymentSessionData: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
> {
return Promise.resolve({})
}
cancelPayment(paymentSessionData: Record<string, unknown>): Promise<PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]> {
return Promise.resolve({});
cancelPayment(
paymentSessionData: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
> {
return Promise.resolve({})
}
deletePayment(paymentSessionData: Record<string, unknown>): Promise<PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]> {
return Promise.resolve({});
deletePayment(
paymentSessionData: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
> {
return Promise.resolve({})
}
updatePaymentData(
sessionId: string,
data: Record<string, unknown>
): Promise<
PaymentProcessorError | PaymentProcessorSessionResponse["session_data"]
> {
return Promise.resolve({})
}
}
@@ -98,4 +142,4 @@ export const defaultPaymentSessionInputData = {
},
currency_code: "usd",
amount: 1000,
}
}
@@ -1,6 +1,5 @@
import { asValue, createContainer } from "awilix"
import { MockRepository } from "medusa-test-utils"
import PaymentProviderService from "../payment-provider"
import {
defaultContainer,
defaultPaymentSessionInputData,
@@ -8,7 +7,7 @@ import {
} from "../__fixtures__/payment-provider"
import { testPayServiceMock } from "../__mocks__/test-pay"
import { EOL } from "os"
import { PaymentSessionStatus, RefundReason } from "../../models";
import { PaymentSessionStatus, RefundReason } from "../../models"
describe(`PaymentProviderService`, () => {
const container = createContainer({}, defaultContainer)
@@ -144,8 +143,8 @@ describe(`PaymentProviderService`, () => {
amount: 100,
currency_code: "usd",
cart: {
id: "cart-test"
}
id: "cart-test",
},
}
)
@@ -564,17 +563,21 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
provider_id: defaultPaymentSessionInputData.provider_id,
payment_session: {
id: sessionId,
data: { id: externalId }
}
data: { id: externalId },
},
}
const container = createContainer({}, defaultContainer)
const mockPaymentProcessor = new PaymentProcessor(container)
mockPaymentProcessor.retrievePayment = jest.fn().mockReturnValue(Promise.resolve({}))
mockPaymentProcessor.retrievePayment = jest
.fn()
.mockReturnValue(Promise.resolve({}))
container
.register(paymentProcessorResolutionKey, asValue(mockPaymentProcessor))
container.register(
paymentProcessorResolutionKey,
asValue(mockPaymentProcessor)
)
const providerService = container.resolve(paymentServiceResolutionKey)
@@ -584,7 +587,9 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const provider = container.resolve(paymentProcessorResolutionKey)
expect(provider.retrievePayment).toBeCalledTimes(1)
expect(provider.retrievePayment).toBeCalledWith(paymentInput.payment_session.data)
expect(provider.retrievePayment).toBeCalledWith(
paymentInput.payment_session.data
)
})
it("throw an error using the provider error response", async () => {
@@ -621,27 +626,27 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const paymentSession = {
id: "test-session",
data: { id: externalId },
provider_id: paymentProviderId
provider_id: paymentProviderId,
}
const context = { ip: "0.0.0.0" }
const container = createContainer({}, defaultContainer)
const mockPaymentProcessor = new PaymentProcessor(container)
mockPaymentProcessor.authorizePayment = jest.fn().mockReturnValue(Promise.resolve({}))
mockPaymentProcessor.authorizePayment = jest
.fn()
.mockReturnValue(Promise.resolve({}))
container
.register(paymentProcessorResolutionKey, asValue(mockPaymentProcessor))
.register(
"paymentSessionRepository",
asValue(
MockRepository({
findOne: jest
.fn()
.mockImplementation(async () => ({ data: {} })),
})
)
"paymentSessionRepository",
asValue(
MockRepository({
findOne: jest.fn().mockImplementation(async () => ({ data: {} })),
})
)
)
const providerService = container.resolve(paymentServiceResolutionKey)
@@ -651,7 +656,10 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const provider = container.resolve(paymentProcessorResolutionKey)
expect(provider.authorizePayment).toBeCalledTimes(1)
expect(provider.authorizePayment).toBeCalledWith(paymentSession.data, context)
expect(provider.authorizePayment).toBeCalledWith(
paymentSession.data,
context
)
})
it("throw an error using the provider error response", async () => {
@@ -688,26 +696,26 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const payment = {
id: "payment-id",
data: { id: externalId },
provider_id: paymentProviderId
provider_id: paymentProviderId,
}
const container = createContainer({}, defaultContainer)
const mockPaymentProcessor = new PaymentProcessor(container)
mockPaymentProcessor.cancelPayment = jest.fn().mockReturnValue(Promise.resolve())
mockPaymentProcessor.cancelPayment = jest
.fn()
.mockReturnValue(Promise.resolve())
container
.register(paymentProcessorResolutionKey, asValue(mockPaymentProcessor))
.register(
"paymentRepository",
asValue(
MockRepository({
findOne: jest
.fn()
.mockImplementation(async () => payment),
})
)
"paymentRepository",
asValue(
MockRepository({
findOne: jest.fn().mockImplementation(async () => payment),
})
)
)
const providerService = container.resolve(paymentServiceResolutionKey)
@@ -739,9 +747,7 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const providerService = container.resolve(paymentServiceResolutionKey)
const err = await providerService
.cancelPayment(payment)
.catch((e) => e)
const err = await providerService.cancelPayment(payment).catch((e) => e)
expect(err.message).toBe(
`${errResponse.error}:${EOL}${errResponse.detail}`
@@ -752,7 +758,7 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
describe("getStatus", () => {
const payment = {
data: { id: "id" },
provider_id: paymentProviderId
provider_id: paymentProviderId,
}
const container = createContainer({}, defaultContainer)
@@ -765,15 +771,13 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
container
.register(paymentProcessorResolutionKey, asValue(mockPaymentProcessor))
.register(
"paymentRepository",
asValue(
MockRepository({
findOne: jest
.fn()
.mockImplementation(async () => payment),
})
)
"paymentRepository",
asValue(
MockRepository({
findOne: jest.fn().mockImplementation(async () => payment),
})
)
)
const providerService = container.resolve(paymentServiceResolutionKey)
@@ -792,26 +796,26 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const payment = {
data: { id: externalId },
id: "payment-id",
provider_id: paymentProviderId
provider_id: paymentProviderId,
}
const container = createContainer({}, defaultContainer)
const mockPaymentProcessor = new PaymentProcessor(container)
mockPaymentProcessor.capturePayment = jest.fn().mockReturnValue(Promise.resolve(payment.data))
mockPaymentProcessor.capturePayment = jest
.fn()
.mockReturnValue(Promise.resolve(payment.data))
container
.register(paymentProcessorResolutionKey, asValue(mockPaymentProcessor))
.register(
"paymentRepository",
asValue(
MockRepository({
findOne: jest
.fn()
.mockImplementation(async () => payment),
})
)
"paymentRepository",
asValue(
MockRepository({
findOne: jest.fn().mockImplementation(async () => payment),
})
)
)
const providerService = container.resolve(paymentServiceResolutionKey)
@@ -843,9 +847,7 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const providerService = container.resolve(paymentServiceResolutionKey)
const err = await providerService
.capturePayment(payment)
.catch((e) => e)
const err = await providerService.capturePayment(payment).catch((e) => e)
expect(err.message).toBe(
`${errResponse.error}:${EOL}${errResponse.detail}`
@@ -858,62 +860,85 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
jest.clearAllMocks()
})
const payments = [{
id: "p1",
captured_at: new Date(),
data: { id: "id1" },
amount: 1000,
amount_refunded: 0,
provider_id: paymentProviderId,
}, {
id: "p2",
captured_at: new Date(),
data: { id: "id2" },
amount: 1000,
amount_refunded: 0,
provider_id: paymentProviderId,
}, {
id: "p3",
captured_at: new Date(),
data: { id: "id3" },
amount: 1000,
amount_refunded: 1000, // already fully refunded
provider_id: paymentProviderId,
}]
const payments = [
{
id: "p1",
captured_at: new Date(),
data: { id: "id1" },
amount: 1000,
amount_refunded: 0,
provider_id: paymentProviderId,
},
{
id: "p2",
captured_at: new Date(),
data: { id: "id2" },
amount: 1000,
amount_refunded: 0,
provider_id: paymentProviderId,
},
{
id: "p3",
captured_at: new Date(),
data: { id: "id3" },
amount: 1000,
amount_refunded: 1000, // already fully refunded
provider_id: paymentProviderId,
},
]
const container = createContainer({}, defaultContainer)
const mockPaymentProcessor = new PaymentProcessor(container)
mockPaymentProcessor.refundPayment = jest.fn().mockImplementation(async (data) => data)
mockPaymentProcessor.refundPayment = jest
.fn()
.mockImplementation(async (data) => data)
container
.register(paymentProcessorResolutionKey, asValue(mockPaymentProcessor))
.register(
"paymentRepository",
asValue(
MockRepository({
find: jest
.fn()
.mockImplementation(async () => payments),
})
)
"paymentRepository",
asValue(
MockRepository({
find: jest.fn().mockImplementation(async () => payments),
})
)
)
const providerService = container.resolve(paymentServiceResolutionKey)
const paymentRepo = container.resolve("paymentRepository")
it("successfully refund the payments", async () => {
await providerService.refundPayment(payments, 1500, RefundReason.OTHER, "note")
await providerService.refundPayment(
payments,
1500,
RefundReason.OTHER,
"note"
)
const provider = container.resolve(paymentProcessorResolutionKey)
expect(provider.refundPayment).toBeCalledTimes(2)
expect(provider.refundPayment).toHaveBeenNthCalledWith(1, payments[0].data, 1000)
expect(provider.refundPayment).toHaveBeenNthCalledWith(2, payments[1].data, 500)
expect(provider.refundPayment).toHaveBeenNthCalledWith(
1,
payments[0].data,
1000
)
expect(provider.refundPayment).toHaveBeenNthCalledWith(
2,
payments[1].data,
500
)
expect(paymentRepo.save).toBeCalledTimes(2)
expect(paymentRepo.save).toHaveBeenNthCalledWith(1, expect.objectContaining({ amount_refunded: 1000 }))
expect(paymentRepo.save).toHaveBeenNthCalledWith(2, expect.objectContaining({ amount_refunded: 500 }))
expect(paymentRepo.save).toHaveBeenNthCalledWith(
1,
expect.objectContaining({ amount_refunded: 1000 })
)
expect(paymentRepo.save).toHaveBeenNthCalledWith(
2,
expect.objectContaining({ amount_refunded: 500 })
)
})
it("throw an error using the provider error response", async () => {
@@ -935,9 +960,7 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const providerService = container.resolve(paymentServiceResolutionKey)
const err = await providerService
.refundPayment(payments)
.catch((e) => e)
const err = await providerService.refundPayment(payments).catch((e) => e)
expect(err.message).toBe(
`${errResponse.error}:${EOL}${errResponse.detail}`
@@ -958,16 +981,25 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
const container = createContainer({}, defaultContainer)
const mockPaymentProcessor = new PaymentProcessor(container)
mockPaymentProcessor.refundPayment = jest.fn().mockImplementation(async (data) => data)
mockPaymentProcessor.refundPayment = jest
.fn()
.mockImplementation(async (data) => data)
container
.register(paymentProcessorResolutionKey, asValue(mockPaymentProcessor))
container.register(
paymentProcessorResolutionKey,
asValue(mockPaymentProcessor)
)
const providerService = container.resolve(paymentServiceResolutionKey)
const paymentRepo = container.resolve("paymentRepository")
it("successfully refund the payments", async () => {
await providerService.refundFromPayment(payment, 500, RefundReason.OTHER, "note")
await providerService.refundFromPayment(
payment,
500,
RefundReason.OTHER,
"note"
)
const provider = container.resolve(paymentProcessorResolutionKey)
@@ -975,7 +1007,9 @@ describe("PaymentProviderService using AbstractPaymentProcessor", () => {
expect(provider.refundPayment).toBeCalledWith(payment.data, 500)
expect(paymentRepo.save).toBeCalledTimes(1)
expect(paymentRepo.save).toBeCalledWith(expect.objectContaining({ amount_refunded: 500 }))
expect(paymentRepo.save).toBeCalledWith(
expect.objectContaining({ amount_refunded: 500 })
)
})
it("throw an error using the provider error response", async () => {
@@ -575,18 +575,23 @@ export default class PaymentProviderService extends TransactionBaseService {
const provider = this.retrieveProvider(paymentSession.provider_id)
let updatedData
if (provider instanceof AbstractPaymentProcessor) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
`The payment provider ${paymentSession.provider_id} is of type PaymentProcessor. PaymentProcessors cannot update payment session data.`
)
const res = await provider.updatePaymentData(paymentSession.id, data)
if ("error" in res) {
this.throwFromPaymentProcessorError(res as PaymentProcessorError)
} else {
updatedData = res
}
} else {
session.data = await provider
updatedData = await provider
.withTransaction(transactionManager)
.updatePaymentData(paymentSession.data, data)
session.status = paymentSession.status
}
Object.assign(session.data, updatedData)
session.status = paymentSession.status
const sessionRepo = transactionManager.withRepository(
this.paymentSessionRepository_
)