-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Description
Package.json file
{
"name": "medusa-starter-default",
"version": "0.0.1",
"description": "A starter for Medusa projects.",
"author": "Medusa (https://medusajs.com)",
"license": "MIT",
"keywords": [
"sqlite",
"postgres",
"typescript",
"ecommerce",
"headless",
"medusa"
],
"scripts": {
"build": "medusa build",
"seed": "medusa exec ./src/scripts/seed.ts",
"start": "medusa start -p 9777",
"dev": "medusa develop -p 9777",
"test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --forceExit",
"test:integration:modules": "TEST_TYPE=integration:modules NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
"test:unit": "TEST_TYPE=unit NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
"full-cost-reconcile": "node -r dotenv/config -r ts-node/register src/scripts/full-cost-reconciliation.ts",
"per-message-costs": "node -r dotenv/config -r ts-node/register src/scripts/per-message-cost-tracker.ts",
"monitor-db-pool": "node -r dotenv/config -r ts-node/register src/scripts/monitor-db-pool.ts",
"backfill-tiers": "medusa exec ./src/scripts/backfill-customer-tiers-merged.ts"
},
"dependencies": {
"@medusajs/admin-sdk": "latest",
"@medusajs/cli": "latest",
"@medusajs/framework": "latest",
"@medusajs/medusa": "latest",
"@mikro-orm/core": "6.4.3",
"@mikro-orm/knex": "6.4.3",
"@mikro-orm/migrations": "6.4.3",
"@mikro-orm/postgresql": "6.4.3",
"@sendgrid/eventwebhook": "^8.0.0",
"awilix": "^8.0.1",
"multer": "^1.4.5-lts.1",
"pg": "^8.13.0",
"twilio": "^5.3.3"
},
"devDependencies": {
"@medusajs/test-utils": "latest",
"@mikro-orm/cli": "6.4.3",
"@swc/core": "1.5.7",
"@swc/jest": "^0.2.36",
"@types/jest": "^29.5.13",
"@types/multer": "^1.4.12",
"@types/node": "^20.0.0",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.2.25",
"jest": "^29.7.0",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"ts-node": "^10.9.2",
"typescript": "^5.6.2",
"vite": "^5.2.11",
"yalc": "^1.0.0-pre.53"
},
"engines": {
"node": ">=20"
},
"packageManager": "[email protected]+sha512.f26f951f67de0c6a33ee381e5ff364709c87e70eb5e65c694e4facde3512f1fa80b8679e6ba31ce7d340fbb46f08dd683af9457e240f25a204be7427940d767e"
}Node.js version
v20.18.1
Database and its version
PostgreSQL 15.6
Operating system name and version
Ubuntu 25.04
Browser name
Brave
What happended?
The stripe endpoint /capture is called twice on a processPaymentWorkflow event whether manual or automatic capture from medusa-config.ts. I even tested with two different version frontend package versions and see the results below:
Default versions used by medusajs packages (core medusa stripe integration and nextjs-starter)
backend medusajs:
@medusajs/[email protected] invalid: "latest" from the root project
└─┬ @medusajs/[email protected]
└── [email protected]
frontend nextjs:
├── @stripe/[email protected]
├── @stripe/[email protected]
Here find the following: Multiple calls to stripe /capture api endpoint
- top manual capture
"capture_method": "manual" - bottom automatic
"capture_method": "automatic"
Different package version frontend
backend medusajs:
@medusajs/[email protected] invalid: "latest" from the root project
└─┬ @medusajs/[email protected]
└── [email protected]
frontend nextjs:
├── @stripe/[email protected]
├── @stripe/[email protected]
Here find the following: mutiple calls to strpipe /capture api endpoint on manual, 1 /capture and 1 /cancel on auto
- top manual capture
"capture_method": "manual" - bottom automatic
"capture_method": "automatic"
Payment is successfully captured in both scenarios with both package versions. However at times there can occur a race condition between the capture events and the .confirmPayment on the nextjs frontend leading to a refund after an order is successfully processed and fulfilled in the case of digital products.
Expected behavior
- payment intent created
- .confirmPayment - if
capture: truethis is where payment is collected as"capture_method": "automatic"is passed due to the config below in medusa-config.ts
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "@medusajs/medusa/payment-stripe",
id: "stripe",
options: {
apiKey: process.env.STRIPE_API_KEY,
webhookSecret: process.env.STRIPE_WEBHOOK,
automatic_payment_methods: true,
capture: true,
},
},
],
},
},- order created after success response from .confirmPayment
- There would be no need for the /capture api calls if
capture: true
Actual behavior
- payment intent created
- .confirmPayment - payment is captured - race conditions occur 1/1000
- order created after success response from .confirmPayment
processPaymentWorkflow- /capture api callprocessPaymentWorkflow- /capture api call (from webhook response)