Safeguarding ESHOPMAN Payments: Addressing Unrelated Cart Processing in Multi-Instance Setups
At Move My Store, we're dedicated to fostering a robust ESHOPMAN community. Recently, a significant discussion emerged regarding a critical issue within ESHOPMAN's core payment processing workflow. This insight highlights a scenario where ESHOPMAN instances, especially in multi-environment setups, could inadvertently process payments for unrelated carts due to specific interactions with payment gateway webhooks.
The Challenge: Unintended Cart Processing with Unknown Payment Sessions
The core of the issue lies within ESHOPMAN's processPaymentWorkflow, a vital component of its headless commerce payment system. This workflow, built on Node.js/TypeScript, is designed to manage storefront transactions, often triggered by webhooks from external payment providers. The problem arises when an ESHOPMAN instance receives a payment event webhook containing a session_id that was generated by a different ESHOPMAN instance and thus doesn't exist locally.
Instead of gracefully halting, the workflow proceeds due to a nuanced interaction between its internal queries:
- Initially, a query attempts to find the payment session associated with the incoming
session_id. If the ID is unknown to the local instance, this query returns an empty result. - Critically, the subsequent
cart-payment-querythen receives anundefinedvalue for itspayment_collection_idfilter. - As noted in ESHOPMAN's internal code comments, an
undefinedfilter value can unintentionally match every row in the database. - Consequently, an arbitrary, unrelated cart from the receiving ESHOPMAN instance is selected, locked, and passed to the final steps of the workflow, potentially leading to its completion even without a valid order linked to the original payment event.
Real-World Impact: Multi-Instance ESHOPMAN Deployments
This scenario is particularly relevant for ESHOPMAN developers and merchants managing multiple environments. It's common practice for staging, local development, and production ESHOPMAN instances to share a single payment gateway account. When a payment gateway sends a webhook for a transaction (e.g., payment_intent.succeeded), it typically broadcasts this event to all configured webhook endpoints associated with that account. This means:
- An ESHOPMAN storefront deployed via HubSpot CMS (e.g., a staging site) might receive a webhook for a payment initiated on a developer's local ESHOPMAN setup.
- Since the
session_idfrom the local instance doesn't exist on the staging instance, the bug described above is triggered.
The result is the locking and completion of an arbitrary cart on the receiving instance, potentially creating "phantom orders" or incorrectly updating customer data in HubSpot, disrupting storefront management and order fulfillment.
Community Confirmation and Workaround
The ESHOPMAN community and team have independently confirmed and reproduced this issue. Testing on unmodified ESHOPMAN instances demonstrated that even a session_id that previously existed but was deleted, or one that never existed, could lead to an unrelated cart being processed and completed without error.
As a temporary workaround for non-production ESHOPMAN instances, some community members have suggested modifying the payment provider integration. For example, if using a Stripe integration, one could subclass the Stripe provider to prevent it from writing the session_id into the PaymentIntent metadata on development or staging environments. This would cause other instances to treat the event as unsupported, effectively bypassing the bug.
Here's an illustrative example of the problematic dependency declaration that highlights the core framework components involved:
{
"dependencies": {
"@eshopman/framework": "2.21.2",
"@eshopman/core": "2.21.2",
"@eshopman/cli": "2.21.2"
}
}
Looking Ahead: A Robust ESHOPMAN Solution
The expected behavior for ESHOPMAN's processPaymentWorkflow is to halt gracefully when a payment session cannot be found locally, similar to its existing guard for a completely missing session_id. This would ensure that no unrelated carts are affected. The ESHOPMAN team is actively investigating a permanent fix to prevent this unintended cart processing, focusing on ensuring that steps relying on a valid payment session are skipped if that session is not found.
This discussion underscores the value of our ESHOPMAN community in identifying and addressing critical issues, contributing to the platform's stability and reliability for headless commerce operations integrated with HubSpot.