This PR adds a couple new statuses to the payment collection and payment webhook results. The payment collection will now be marked as "completed" once the captured amount is the full amount of the payment collection. There are several things left to improve the payment setup, so non-happy-path cases are handled correctly. 1. Currently the payment session and payment models serve a very similar purpose. Part of the information is found on one, and the other part on the other model, without any clear reason for doing so. We can simplify the payment module and the data models simply by merging the two. 2. We need to handle failures more gracefully, such as setting the payment session status to failed when such a webhook comes in. 3. We should convert the payment collection status and the different amounts to calculated fields from the payment session, captures, and refunds, as they can easily be a source of inconsistencies.
64 lines
1.6 KiB
TypeScript
64 lines
1.6 KiB
TypeScript
import { processPaymentWorkflow } from "@medusajs/core-flows"
|
|
import {
|
|
IPaymentModuleService,
|
|
ProviderWebhookPayload,
|
|
} from "@medusajs/framework/types"
|
|
import {
|
|
Modules,
|
|
PaymentActions,
|
|
PaymentWebhookEvents,
|
|
} from "@medusajs/framework/utils"
|
|
import { SubscriberArgs, SubscriberConfig } from "../types/subscribers"
|
|
|
|
type SerializedBuffer = {
|
|
data: ArrayBuffer
|
|
type: "Buffer"
|
|
}
|
|
|
|
export default async function paymentWebhookhandler({
|
|
event,
|
|
container,
|
|
}: SubscriberArgs<ProviderWebhookPayload>) {
|
|
const paymentService: IPaymentModuleService = container.resolve(
|
|
Modules.PAYMENT
|
|
)
|
|
|
|
const input = event.data
|
|
|
|
if (
|
|
(input.payload?.rawData as unknown as SerializedBuffer)?.type === "Buffer"
|
|
) {
|
|
input.payload.rawData = Buffer.from(
|
|
(input.payload.rawData as unknown as SerializedBuffer).data
|
|
)
|
|
}
|
|
|
|
const processedEvent = await paymentService.getWebhookActionAndData(input)
|
|
|
|
if (
|
|
processedEvent?.action === PaymentActions.NOT_SUPPORTED ||
|
|
// Currently none of these are handled by the processPaymentWorkflow, so we ignore them.
|
|
// Remove once the processPaymentWorkflow is handling them.
|
|
processedEvent?.action === PaymentActions.CANCELED ||
|
|
processedEvent?.action === PaymentActions.FAILED ||
|
|
processedEvent?.action === PaymentActions.REQUIRES_MORE
|
|
) {
|
|
return
|
|
}
|
|
|
|
if (!processedEvent.data) {
|
|
return
|
|
}
|
|
|
|
await processPaymentWorkflow(container).run({
|
|
input: processedEvent,
|
|
})
|
|
}
|
|
|
|
export const config: SubscriberConfig = {
|
|
event: PaymentWebhookEvents.WebhookReceived,
|
|
context: {
|
|
subscriberId: "payment-webhook-handler",
|
|
},
|
|
}
|