Summary
In client/resources/simplestore, when an order's invoice expires without
being paid, the order is set to status paid. An unpaid, expired order is
therefore indistinguishable from a completed sale, and any consumer that reacts
to the paid status (via the StatusChanged callback) registers a false payment.
Details
invoiceExpired is a near-verbatim copy of invoiceSettled and still sets the
order status to StatusPaid. In client/resources/simplestore/simplestore.go
(invoiceExpired):
// Mark order as paid. First, reload the full order from disk. // copied comment
...
// Now update status.
order.Status = StatusPaid // wrong for an expired/unpaid order
Orders expire one hour after placement (ExpiresTS = time.Now().Add(time.Hour)
in handlers.go), so any order not paid within that window flips to paid.
The rest of invoiceExpired is already correct: it does not send the digital
files, it logs the order "as expired", and it DMs the buyer that the order "has
been identified as expired". Only the status assignment (and the copied
// Mark order as paid. comment) is wrong.
Impact
- An expired, unpaid order shows as
paid to the merchant.
- A
StatusChanged consumer keying on StatusPaid (e.g. to notify "payment
received") fires a false positive.
- Since the file-send loop is skipped, the order is
paid with no delivery,
which is itself inconsistent.
Expected
An expired, unpaid order should be a distinct, non-paid terminal state.
Suggested fix
Minimal: set the existing (currently unused) StatusCanceled instead of
StatusPaid, and fix the copied comment:
- // Mark order as paid. First, reload the full order from disk.
+ // Mark order as canceled. First, reload the full order from disk.
...
- order.Status = StatusPaid
+ order.Status = StatusCanceled
Alternatively, introduce a dedicated StatusExpired to distinguish an expired
order from a merchant/buyer cancelation. Happy to open a PR for whichever you
prefer.
Related (separate, optional)
handleAdminUpdateOrderStatus in admin.go writes a paid status without
running the file-send loop, so the admin "set paid" path never delivers digital
downloads. Noting in case it is of interest; can file separately.
Version
Present on master and in the latest release (v0.2.4).
Summary
In
client/resources/simplestore, when an order's invoice expires withoutbeing paid, the order is set to status
paid. An unpaid, expired order istherefore indistinguishable from a completed sale, and any consumer that reacts
to the paid status (via the
StatusChangedcallback) registers a false payment.Details
invoiceExpiredis a near-verbatim copy ofinvoiceSettledand still sets theorder status to
StatusPaid. Inclient/resources/simplestore/simplestore.go(
invoiceExpired):Orders expire one hour after placement (
ExpiresTS = time.Now().Add(time.Hour)in
handlers.go), so any order not paid within that window flips topaid.The rest of
invoiceExpiredis already correct: it does not send the digitalfiles, it logs the order "as expired", and it DMs the buyer that the order "has
been identified as expired". Only the status assignment (and the copied
// Mark order as paid.comment) is wrong.Impact
paidto the merchant.StatusChangedconsumer keying onStatusPaid(e.g. to notify "paymentreceived") fires a false positive.
paidwith no delivery,which is itself inconsistent.
Expected
An expired, unpaid order should be a distinct, non-paid terminal state.
Suggested fix
Minimal: set the existing (currently unused)
StatusCanceledinstead ofStatusPaid, and fix the copied comment:Alternatively, introduce a dedicated
StatusExpiredto distinguish an expiredorder from a merchant/buyer cancelation. Happy to open a PR for whichever you
prefer.
Related (separate, optional)
handleAdminUpdateOrderStatusinadmin.gowrites apaidstatus withoutrunning the file-send loop, so the admin "set paid" path never delivers digital
downloads. Noting in case it is of interest; can file separately.
Version
Present on
masterand in the latest release (v0.2.4).