How do I stop a MonCash payment from being fulfilled twice?

poze 2 months ago656 gadeen

7

Sometimes an order gets marked paid twice and we ship twice: the customer refreshes the return page, and our background checker also finds the payment. How do I make fulfilment safe?

Dyagnostik IA

Se IA ki fè l. Se pa yon repons — kominote a anba a konfime oswa korije l. Toujou verifye anvan ou fye l.

1 Repons

3
✓
✓ Repons yo aksepte

Make "mark as paid" idempotent at the database level, not just in application code. Two requests arriving at the same moment will both pass an if (order.status !== 'PAID') check.

1. Store the MonCash transaction id with a unique constraint

ALTER TABLE payments ADD CONSTRAINT payments_moncash_tx_unique UNIQUE (moncash_transaction_id);

2. Transition the order with a conditional update

async function markPaidOnce(orderId: string, transactionId: string) {
  return db.$transaction(async (tx) => {
    // only one caller can move PENDING → PAID
    const { count } = await tx.order.updateMany({
      where: { id: orderId, status: "PENDING" },
      data: { status: "PAID", paidAt: new Date() },
    });
    if (count === 0) return false; // someone else already did it
 
    await tx.payment.create({ data: { orderId, provider: "MONCASH", moncashTransactionId: transactionId } });
    return true;
  });
}

Only the caller that gets true sends the confirmation email or ships. Everyone else just shows "already paid".

3. Use one orderId per payment attempt. If a customer abandons and retries, create a new attempt with its own id that links back to the order. MonCash rejects a duplicate orderId, and you get a clean audit trail.

Konekte pou di lòt moun si li te mache.

answered 2 months ago

Sign in and verify your email to post an answer.