fix(medusa-payment-stripe): handle webhook sirialization failure (#2607)
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"medusa-payment-stripe": patch
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(medusa-payment-stripe): handle webhook sirialization failure
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { PostgresError } from "@medusajs/medusa/src/utils"
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const signature = req.headers["stripe-signature"]
|
const signature = req.headers["stripe-signature"]
|
||||||
|
|
||||||
@@ -16,7 +18,6 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
async function handleCartPayments(event, req, res, cartId) {
|
async function handleCartPayments(event, req, res, cartId) {
|
||||||
const manager = req.scope.resolve("manager")
|
const manager = req.scope.resolve("manager")
|
||||||
const cartService = req.scope.resolve("cartService")
|
|
||||||
const orderService = req.scope.resolve("orderService")
|
const orderService = req.scope.resolve("orderService")
|
||||||
|
|
||||||
const order = await orderService
|
const order = await orderService
|
||||||
@@ -33,13 +34,26 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "payment_intent.amount_capturable_updated":
|
case "payment_intent.amount_capturable_updated":
|
||||||
if (!order) {
|
try {
|
||||||
await manager.transaction(async (manager) => {
|
await manager.transaction(async (manager) => {
|
||||||
const cartServiceTx = cartService.withTransaction(manager)
|
await paymentIntentAmountCapturableEventHandler({
|
||||||
await cartServiceTx.setPaymentSession(cartId, "stripe")
|
order,
|
||||||
await cartServiceTx.authorizePayment(cartId)
|
cartId,
|
||||||
await orderService.withTransaction(manager).createFromCart(cartId)
|
container: req.scope,
|
||||||
|
transactionManager: manager,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
} catch (err) {
|
||||||
|
let message = `Stripe webhook ${event} handling failed\n${
|
||||||
|
err?.detail ?? err?.message
|
||||||
|
}`
|
||||||
|
if (err?.code === PostgresError.SERIALIZATION_FAILURE) {
|
||||||
|
message = `Stripe webhook ${event} handle failed. This can happen when this webhook is triggered during a cart completion and can be ignored. This event should be retried automatically.\n${
|
||||||
|
err?.detail ?? err?.message
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
this.logger_.warn(message)
|
||||||
|
return res.sendStatus(409)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@@ -85,8 +99,27 @@ export default async (req, res) => {
|
|||||||
const resourceId = paymentIntent.metadata.resource_id
|
const resourceId = paymentIntent.metadata.resource_id
|
||||||
|
|
||||||
if (isPaymentCollection(resourceId)) {
|
if (isPaymentCollection(resourceId)) {
|
||||||
await handlePaymentCollection(event, req, res, resourceId, paymentIntentId)
|
await handlePaymentCollection(event, req, res, resourceId, paymentIntent.id)
|
||||||
} else {
|
} else {
|
||||||
await handleCartPayments(event, req, res, cartId ?? resourceId)
|
await handleCartPayments(event, req, res, cartId ?? resourceId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function paymentIntentAmountCapturableEventHandler({
|
||||||
|
order,
|
||||||
|
cartId,
|
||||||
|
container,
|
||||||
|
transactionManager,
|
||||||
|
}) {
|
||||||
|
if (!order) {
|
||||||
|
const cartService = container.resolve("cartService")
|
||||||
|
const orderService = container.resolve("orderService")
|
||||||
|
|
||||||
|
const cartServiceTx = cartService.withTransaction(transactionManager)
|
||||||
|
await cartServiceTx.setPaymentSession(cartId, "stripe")
|
||||||
|
await cartServiceTx.authorizePayment(cartId)
|
||||||
|
await orderService
|
||||||
|
.withTransaction(transactionManager)
|
||||||
|
.createFromCart(cartId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { PaymentProviderDataInput } from "../types/payment-collection"
|
|||||||
import { FlagRouter } from "../utils/flag-router"
|
import { FlagRouter } from "../utils/flag-router"
|
||||||
import OrderEditingFeatureFlag from "../loaders/feature-flags/order-editing"
|
import OrderEditingFeatureFlag from "../loaders/feature-flags/order-editing"
|
||||||
import PaymentService from "./payment"
|
import PaymentService from "./payment"
|
||||||
|
import { Logger } from "../types/global"
|
||||||
|
|
||||||
type PaymentProviderKey = `pp_${string}` | "systemPaymentProviderService"
|
type PaymentProviderKey = `pp_${string}` | "systemPaymentProviderService"
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -30,6 +31,7 @@ type InjectedDependencies = {
|
|||||||
refundRepository: typeof RefundRepository
|
refundRepository: typeof RefundRepository
|
||||||
paymentService: PaymentService
|
paymentService: PaymentService
|
||||||
featureFlagRouter: FlagRouter
|
featureFlagRouter: FlagRouter
|
||||||
|
logger: Logger
|
||||||
} & {
|
} & {
|
||||||
[key in `${PaymentProviderKey}`]:
|
[key in `${PaymentProviderKey}`]:
|
||||||
| AbstractPaymentService
|
| AbstractPaymentService
|
||||||
@@ -48,6 +50,7 @@ export default class PaymentProviderService extends TransactionBaseService {
|
|||||||
protected readonly paymentProviderRepository_: typeof PaymentProviderRepository
|
protected readonly paymentProviderRepository_: typeof PaymentProviderRepository
|
||||||
protected readonly paymentRepository_: typeof PaymentRepository
|
protected readonly paymentRepository_: typeof PaymentRepository
|
||||||
protected readonly refundRepository_: typeof RefundRepository
|
protected readonly refundRepository_: typeof RefundRepository
|
||||||
|
protected readonly logger_: Logger
|
||||||
|
|
||||||
protected readonly featureFlagRouter_: FlagRouter
|
protected readonly featureFlagRouter_: FlagRouter
|
||||||
|
|
||||||
@@ -61,6 +64,7 @@ export default class PaymentProviderService extends TransactionBaseService {
|
|||||||
this.paymentRepository_ = container.paymentRepository
|
this.paymentRepository_ = container.paymentRepository
|
||||||
this.refundRepository_ = container.refundRepository
|
this.refundRepository_ = container.refundRepository
|
||||||
this.featureFlagRouter_ = container.featureFlagRouter
|
this.featureFlagRouter_ = container.featureFlagRouter
|
||||||
|
this.logger_ = container.logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async registerInstalledProviders(providerIds: string[]): Promise<void> {
|
async registerInstalledProviders(providerIds: string[]): Promise<void> {
|
||||||
|
|||||||
Reference in New Issue
Block a user