---
id: CAP-ACC-TRX-007
title: Collect processor payments and resolve uncertainty
feature: FEAT-ACC-TRX-03
product_area: accounting
module: transactions
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
  - CAP-ACC-PAY-002
  - CAP-ACC-PAY-008
  - CAP-ACC-PAY-018
  - CAP-ACC-PAY-019
  - CAP-ACC-SEC-011
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/plans/ACCT-M2-plan.md#D5'
  - 'services-accounting:docs/milestones/plans/ACCT-M2-plan.md#D6'
  - >-
    services-accounting:docs/milestones/plans/ACCT-M2-plan.md#13. Amendment 2026-10-21 18:55 ET: Payrix beside
    Stripe (Andrew)
  - 'services-accounting:docs/milestones/ACCT-M2-take-and-apply-payments.md#WP-U/U2/U3'
  - 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-13'
  - 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#M2-10'
purpose: Staff and Commerce collect card or bank money and recover interrupted outcomes without a second charge.
outcomes:
  - Staff and Commerce collect card or bank money and recover interrupted outcomes without a second charge.
  - >-
    Exhausted lookup raises human review rather than assuming no charge occurred. Bank-debit clearing can
    finish later than the original tender.
concepts:
  - CON-ACC-TRX-003
actors:
  - ACT-ACC-012
  - ACT-ACC-001
  - ACT-ACC-021
  - ACT-ACC-022
  - ACT-ACC-023
  - ACT-ACC-024
surfaces:
  - console
  - api
  - job
permissions:
  - key: accounting.payments.create
    where_checked: api
    scope: tenant
  - key: accounting.payments.read
    where_checked: api
    scope: tenant
  - key: accounting.payments.update
    where_checked: api
    scope: tenant
  - key: accounting.payments.settle
    where_checked: api
    scope: global
  - key: accounting.payment-element.read
    where_checked: api
    scope: tenant
  - key: accounting.payment-element.create
    where_checked: api
    scope: tenant
  - key: accounting.stripe-settings.read
    where_checked: api
    scope: tenant
  - key: accounting.stripe-settings.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-TRX-007-01
    proved_by: [ATS-ACC-TRX-007-01, TST-ACC-TRX-082, TST-ACC-TRX-258]
    statement: >-
      Processor tenders require an active merchant account in the payment’s unit and currency; hosted
      processor fields collect the instrument, and Accounting does not retain its token.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      refuses an inactive merchant account (merchant_account_inactive), charging nothing
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-02
    proved_by: [ATS-ACC-TRX-007-02, TST-ACC-TRX-082, TST-ACC-TRX-241]
    statement: >-
      Financial eligibility and planned allocations are checked before the charge call, preventing rejected
      input from reaching the processor.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      refuses a planned allocation over the line’s balance (over_application), charging nothing
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-03
    proved_by: [ATS-ACC-TRX-007-02, ATS-ACC-TRX-007-12, ATS-ACC-TRX-008-09, ATS-ACC-TRX-009-12, ATS-ACC-TRX-020-09, TST-ACC-TRX-082, TST-ACC-TRX-241]
    statement: >-
      An intent is committed before charging, and its identity limits the attempt to one charge and one
      recorded payment.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      resolves the intent succeeded, naming the payment, claimed and resolved, with the batch chosen at
      initiation
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-01'
  - id: BR-CAP-ACC-TRX-007-04
    proved_by: [ATS-ACC-TRX-007-03, TST-ACC-TRX-082]
    statement: >-
      A definite decline or unreachable charge fails the intent and releases the request key for another
      attempt without recording collected money.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      frees the key: the same key sent again is tendered again, as a new intent (declined again here)
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-05
    proved_by: [ATS-ACC-TRX-007-04, ATS-ACC-TRX-008-09, TST-ACC-TRX-082, TST-ACC-TRX-254]
    statement: >-
      Captured money is always recorded, allocations shrink to the lines’ current balances, and excess remains
      unapplied.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      is capped at what the line owes then and the rest stays unapplied: the charged money is never refused
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-06
    proved_by: [ATS-ACC-TRX-007-05, ATS-ACC-TRX-007-12, ATS-ACC-TRX-009-12, ATS-ACC-TRX-011-10, ATS-ACC-TRX-012-12, ATS-ACC-TRX-020-09, TST-ACC-TRX-015, TST-ACC-TRX-082, TST-ACC-TRX-253]
    statement: >-
      An uncertain processor response leaves the intent processing, and retrying the request performs a lookup
      instead of another charge.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      answers the payment to a replay of the same key, from what the processor holds, with no second charge
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-07
    proved_by: [ATS-ACC-TRX-007-06, TST-ACC-TRX-076]
    statement: >-
      Scheduled lookups follow the environment cadence and require a definite answer; exhausted unresolved
      lookups raise an attention item for human review.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      hands the intent to a person at the last lookup: needs_review, the item published with its facts
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-08
    proved_by: [ATS-ACC-TRX-007-07, TST-ACC-TRX-076]
    statement: >-
      Human resolution requires an unresolved attempt already in review and either records failure or creates
      the payment once using the confirmed processor reference.
    kind: permission
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      refuses both decisions before the last lookup (lost_answer_not_in_review)
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-09
    proved_by: [ATS-ACC-TRX-007-08, TST-ACC-TRX-082]
    statement: An intent whose processor cannot be queried is abandoned after twenty-four hours and logged as an error.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      is abandoned by the sweeper after 24 hours, with its event (FC-17)
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-10
    proved_by: [ATS-ACC-TRX-007-09, ATS-ACC-TRX-007-12, ATS-ACC-TRX-013-10, TST-ACC-TRX-075, TST-ACC-TRX-080, TST-ACC-TRX-082]
    statement: >-
      Electronic checks remain pending until clearing is confirmed, then succeed; a returned debit creates an
      ACH-return reversal.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/payment-reversals.integration.spec.js#it
      settles the one the bank cleared: succeeded, settled_at, its capture item eligible, the settle event
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-11
    proved_by: [ATS-ACC-TRX-007-10, TST-ACC-TRX-011]
    statement: >-
      Only Rhythm staff can use the system route to mark an electronic check settled; customer administrators
      are refused.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/payment-reversals.e2e.spec.js#it is refused the
      settled route as a console administrator: it is a system route (403)
    origin: 'services-accounting:docs/milestones/ACCT-M2-take-and-apply-payments.md#0352'
  - id: BR-CAP-ACC-TRX-007-12
    proved_by: [ATS-ACC-TRX-007-11, TST-ACC-TRX-127, TST-ACC-TRX-271]
    statement: >-
      The processor’s electronic-check capability controls whether bank-account entry appears beside card
      entry, and electronic checks are eligible wherever cards are.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/stripe/payment-client-side-info.integration.spec.js#it
      offers the card alone for mode both when the installation has electronic checks off: asked again once,
      no failure
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M2-plan.md#13. Amendment 2026-10-21 18:55 ET: Payrix
      beside Stripe (Andrew)
  - id: BR-CAP-ACC-TRX-007-13
    proved_by: [ATS-ACC-TRX-007-09, TST-ACC-TRX-075, TST-ACC-TRX-080, TST-ACC-TRX-082]
    statement: >-
      Card captures create reconciliation items immediately, while bank-debit captures become eligible when
      clearing completes.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/tender.integration.spec.js#it
      records the capture as one eligible settlement item keyed payment:<id>:capture, on Stripe’s timing (the
      account names no processor)
    origin: none
    note: >-
      The cited build recommendation does not establish Product approval; the authority gap remains open in
      FND-ACC-TRX-035.
  - id: BR-CAP-ACC-TRX-007-14
    proved_by: []
    statement: >-
      Production processor work uses the Integration Platform gateway; the superseded Stripe options and
      webhook remain exposed and report missing configuration where keys are absent.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: documented
    source: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#M2-10'
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#M2-10'
scenarios:
  - id: SC-CAP-ACC-TRX-007-01
    given: Staff receive Visa details from a member by phone.
    when: Use hosted payment entry to collect against the invoice.
    then: The recorded intent produces one capture and a numbered allocated receipt.
    provenance: test
    source: 'react-console:acceptance/accounting/playwright/journeys/payments/ACT-ACC-0302.spec.ts#ACT-ACC-0302'
  - id: SC-CAP-ACC-TRX-007-02
    given: A charge completed externally but its response did not arrive.
    when: Resubmit the uncertain request using the same key.
    then: Lookup recovers the existing charge and records its payment without charging again.
    provenance: test
    source: 'react-console:acceptance/accounting/playwright/journeys/payments/ACT-ACC-0318.spec.ts#ACT-ACC-0318'
  - id: SC-CAP-ACC-TRX-007-03
    given: The selected merchant destination uses Payrix.
    when: 'Submit a card token that declines, then retry.'
    then: The payment dialog explains the failure and obtains a new session for the next attempt.
    provenance: test
    source: 'react-console:acceptance/accounting/playwright/journeys/payments/ACT-ACC-0362.spec.ts#ACT-ACC-0362'
edge_cases: []
depends_on:
  - CAP-ACC-TRX-020
related:
  - CAP-ACC-TRX-008
  - CAP-ACC-TRX-009
  - CAP-ACC-TRX-012
  - CAP-ACC-TRX-013
journeys:
  - JNY-ACC-TRX-003
evidence:
  - >-
    services-accounting at f47cb263875bbc0c5640fba7dae6785ec32695f8:
    modules/transactions/aws/api/payments.routes.ts (receivePayment for card and bank debit, getPaymentIntent,
    failLostAnswer, settleLostAnswer), payment-reversals.routes.ts (markPaymentSettled), stripe.routes.ts
    (receiveStripeWebhook, getPaymentClientSideInfo, getStripeClientSideInfo, createStripeSetupIntent,
    getStripeSettings, saveStripeSettings); services/payments/payment-receive.ts, integrations-processor.ts,
    integrations-payment-element.ts, intent-sweeper.ts, intent-sweeper-cadence.ts, lost-answer-rules.ts,
    lost-answer-commands.ts, dummy-processor.ts, stripe-processor.ts, ports/payment-processor.ts;
    services/stripe/*; attention/processor-answer-lost.attention.ts;
    aws/logic/payment-intent-sweeper.lambda.ts; db/payment-intents.table.ts, stripe-settings.table.ts,
    stripe-customers.table.ts; docs/accounting/payments.md, payment-processors.md, stripe.md,
    dummy-payment-processor.md; tests integration/services/payments/tender, lost-answers,
    integrations-electronic-check, integrations-binding-context, payment-reversals;
    integration/services/stripe/*; e2e/stripe.e2e.spec.js, payments.e2e.spec.js,
    service-functions-gateway-lost-answer.e2e.spec.js.
  - >-
    react-console at baf6dae382d6f41dce976c7f848667ccc37e076f: components/accounting/payments (the Take Card
    Payment pop-up on the payment provider host); journeys ACT-ACC-0302, 0303, 0318, 0319, 0324, 0346, 0360 to
    0366, 0822, 0823.
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-003, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-SEC-001, TC-SEC-002, TC-SEC-003, TC-SEC-004, TC-CRY-001, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-AVL-001, TC-AVL-004, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-VEN-001, TC-VEN-002, TC-VEN-003, TC-PRV-001, TC-PRV-002]
exercised_by: [FAS-ACC-TRX-03-01, FAS-ACC-TRX-03-02, FAS-ACC-TRX-03-04, FAS-ACC-TRX-03-05]
suites: [TST-ACC-TRX-011, TST-ACC-TRX-015, TST-ACC-TRX-075, TST-ACC-TRX-076, TST-ACC-TRX-080, TST-ACC-TRX-082, TST-ACC-TRX-127, TST-ACC-TRX-241, TST-ACC-TRX-253, TST-ACC-TRX-254, TST-ACC-TRX-258, TST-ACC-TRX-271]
---

# Collect processor payments and resolve uncertainty

## Purpose

Staff and Commerce collect card or bank money and recover interrupted outcomes without a second charge.

## How It Works

Hosted processor entry collects the payment instrument. Accounting validates the planned receipt before contacting the processor and retains an intent for the attempt. A definite success produces the payment and eligible applications. A definite refusal allows a fresh attempt. An uncertain answer remains processing while retries and scheduled work ask what happened. Exhausted lookup raises human review rather than assuming no charge occurred. Bank-debit clearing can finish later than the original tender.

## Relationships

- Coordinate financial commands across applications supplies or continues the related financial work.
- Allocate and relocate received money supplies or continues the related financial work.
- Complete invoice settlement with credit and money supplies or continues the related financial work.
- Return customer money with accountable refunds supplies or continues the related financial work.
- Record receipts that were voided or returned supplies or continues the related financial work.
