ACH Processing
The ach-handler Lambda consumes the site-payments Kinesis stream and processes ACH settlement callbacks for subscription collection attempts. It is the mechanism by which a subscription’s billing_status changes after an ACH debit or refund settles.
ACH Callbacks
A Kinesis event-source filter delivers only the four subscription payment event types; other payment events on the stream (e.g. float disbursements) never invoke the Lambda. The handler dispatches on the payment’s status:
| Kinesis event type | payment.Status | billing_status transition | Side effects |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
Status-only update ( |
|
|
|
User banned unconditionally; admin note added; no user-facing notifications |
Source: pkg/payments/achhandler.go.
A record whose user or subscription lookup returns not-found is logged and skipped as a no-op. Status descriptions live in Subscription Lifecycle; the notification and attribution event contracts (Segment, Iterable, AppsFlyer) live in Events.
The handler does no return attribution — that happens in the warehouse by joining the attempt’s decision context to the payments record; see DynamoDB — Decision Context.
Every processed callback emits the subscriptions.collections.attempt Datadog metric, tagged with method:ACH, the outcome status, institution, and process.
Bannable ACH Return Codes
A returned debit whose return code is in this set bans the user via the User Service and adds an admin note. Any SUBSCRIPTION_CHARGED_BACK event also bans, regardless of code. The set is a flat map of codes — JPMorgan reason codes (AG*, DS*) are independent entries, not aliases:
| Return code | Meaning |
|---|---|
|
Unauthorized debit to consumer account using corporate SEC code |
|
Authorization revoked by customer |
|
Payment stopped |
|
Customer advises not authorized |
|
Customer advises entry not in accordance with the terms of authorization |
|
Corporate customer advises not authorized |
|
Item is ineligible, notice not provided, signature not genuine, or item altered |
|
JPMorgan reason code corresponding to |
|
JPMorgan reason code corresponding to |
|
JPMorgan reason code corresponding to |
Source: pkg/payments/achhandler.go (isBannableACHReturn).
Non-bannable return codes (e.g. R01 insufficient funds, R02 account closed) set billing_status to ERROR and record the code in usio_error without a ban; the subscription re-enters the retry cycle via the collections-job.
|