Skip to content

Commit

Permalink
fix(medusa-payment-stripe): handle webhook sirialization failure (#2607)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien2p authored Nov 20, 2022
1 parent 01a879a commit e09f6e8
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 7 deletions.
6 changes: 6 additions & 0 deletions .changeset/moody-tips-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"medusa-payment-stripe": patch
"@medusajs/medusa": patch
---

fix(medusa-payment-stripe): handle webhook sirialization failure
47 changes: 40 additions & 7 deletions packages/medusa-payment-stripe/src/api/routes/hooks/stripe.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { PostgresError } from "@medusajs/medusa/src/utils"

export default async (req, res) => {
const signature = req.headers["stripe-signature"]

Expand All @@ -16,7 +18,6 @@ export default async (req, res) => {

async function handleCartPayments(event, req, res, cartId) {
const manager = req.scope.resolve("manager")
const cartService = req.scope.resolve("cartService")
const orderService = req.scope.resolve("orderService")

const order = await orderService
Expand All @@ -33,13 +34,26 @@ export default async (req, res) => {
}
break
case "payment_intent.amount_capturable_updated":
if (!order) {
try {
await manager.transaction(async (manager) => {
const cartServiceTx = cartService.withTransaction(manager)
await cartServiceTx.setPaymentSession(cartId, "stripe")
await cartServiceTx.authorizePayment(cartId)
await orderService.withTransaction(manager).createFromCart(cartId)
await paymentIntentAmountCapturableEventHandler({
order,
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
default:
Expand Down Expand Up @@ -85,8 +99,27 @@ export default async (req, res) => {
const resourceId = paymentIntent.metadata.resource_id

if (isPaymentCollection(resourceId)) {
await handlePaymentCollection(event, req, res, resourceId, paymentIntentId)
await handlePaymentCollection(event, req, res, resourceId, paymentIntent.id)
} else {
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)
}
}
4 changes: 4 additions & 0 deletions packages/medusa/src/services/payment-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { PaymentProviderDataInput } from "../types/payment-collection"
import { FlagRouter } from "../utils/flag-router"
import OrderEditingFeatureFlag from "../loaders/feature-flags/order-editing"
import PaymentService from "./payment"
import { Logger } from "../types/global"

type PaymentProviderKey = `pp_${string}` | "systemPaymentProviderService"
type InjectedDependencies = {
Expand All @@ -30,6 +31,7 @@ type InjectedDependencies = {
refundRepository: typeof RefundRepository
paymentService: PaymentService
featureFlagRouter: FlagRouter
logger: Logger
} & {
[key in `${PaymentProviderKey}`]:
| AbstractPaymentService
Expand All @@ -48,6 +50,7 @@ export default class PaymentProviderService extends TransactionBaseService {
protected readonly paymentProviderRepository_: typeof PaymentProviderRepository
protected readonly paymentRepository_: typeof PaymentRepository
protected readonly refundRepository_: typeof RefundRepository
protected readonly logger_: Logger

protected readonly featureFlagRouter_: FlagRouter

Expand All @@ -61,6 +64,7 @@ export default class PaymentProviderService extends TransactionBaseService {
this.paymentRepository_ = container.paymentRepository
this.refundRepository_ = container.refundRepository
this.featureFlagRouter_ = container.featureFlagRouter
this.logger_ = container.logger
}

async registerInstalledProviders(providerIds: string[]): Promise<void> {
Expand Down

0 comments on commit e09f6e8

Please sign in to comment.