Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions JPMorgan.idric
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This repository is the consolidation point for the CLI/API-access programs that
- `Economist.idric` — Economist API checkpoint.
- `Ft.idric` — Financial Times API checkpoint.
- `Guardian.idric` — Guardian API checkpoint.
- `JPMorgan.idric` — J.P. Morgan Online Payments API checkpoint; complete v2 endpoint inventory plus a first read-only payment-retrieval slice.
- `Nyt.idric` — New York Times API checkpoint.
- `Reddit.idric` — Reddit Data API checkpoint, with a synthetic fixture and manual receipt.
- `Stripe.idric` — Stripe API checkpoint; first slice is pinned, read-only Balance access with a synthetic fixture and manual receipt.
Expand All @@ -28,6 +29,6 @@ Where these clients need networking, ICU/Idric-Net remains the intended transpor

## Tests

`make test` runs the existing Amazon and AbeBooks smoke tests. Reddit and Stripe have separate manual compiler checkpoints under `checkpoints/reddit/check` and `checkpoints/stripe/check`; they are not part of `make test` while named Idriç holes remain.
`make test` runs the existing Amazon and AbeBooks smoke tests. Reddit, Stripe, and J.P. Morgan have separate manual compiler checkpoints under `checkpoints/`; they are not part of `make test` while named Idriç holes remain.

See `PROVENANCE.md` for the source branches copied into this repository.
146 changes: 146 additions & 0 deletions checkpoints/jpmorgan/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# J.P. Morgan Online Payments CLI compiler checkpoint

This directory is the Idriç checkpoint for J.P. Morgan's Online Payments API. It is intentionally scoped to Online Payments rather than every API on the J.P. Morgan Payments portal.

The first slice is read-only. The API has operations that create, update, capture, refund, verify, and fraud-score payment activity; money-moving writes do not belong in the first transport/compiler checkpoint.

## Command contract

```text
jpmorgan version
jpmorgan endpoints
jpmorgan url payment TRANSACTION_ID
jpmorgan fixture FILE
jpmorgan payment TRANSACTION_ID
```

### `version`

Print the Online Payments API specification version used for this pass:

```text
2.19.0
```

The URL major version remains `v2`; the specification release is tracked separately because J.P. Morgan updates fields and enums within that major-version surface.

### `endpoints`

No network. Print the complete Online Payments endpoint inventory captured in `SURFACE.md` as TSV:

```text
method path action
```

This includes all 16 method/path operations in the current surface pass: payments, captures, refunds, verifications, and fraud checks.

### `url payment`

No network. Build the mock-environment URL for transaction-id retrieval:

```text
https://api-mock.payments.jpmorgan.com/api/v2/payments/TRANSACTION_ID
```

### `fixture`

No network. Read an Online Payments payment-response-shaped JSON file and emit TSV.

The committed synthetic fixture is:

```text
fixture/payment.json
```

Expected output is:

```text
fixture/expected.tsv
```

Columns are:

```text
transaction_id request_id state status code amount currency
```

`amount` remains the integer value returned by the API; the checkpoint does not guess a decimal convention from the currency.

### `payment`

Retrieve one payment by transaction ID from the mock Online Payments v2 base, decode the same shape as the fixture, and emit the same TSV.

The process environment supplies:

```text
JPMORGAN_ACCESS_TOKEN=...
JPMORGAN_MERCHANT_ID=...
```

The request seam carries:

```text
Authorization: Bearer ACCESS_TOKEN
merchant-id: MERCHANT_ID
request-id: freshly generated UUID
Accept: application/json
```

Token acquisition is deliberately outside this first slice. J.P. Morgan uses OAuth 2.0 client credentials; a separately acquired bearer token is enough to exercise the client without putting client secrets into this repository or command-line arguments.

## Idriç and ICU

`idric/JPMorgan.idric` is the implementation target.

ICU/Idric-Net remains the networking boundary. The J.P. Morgan checkpoint adds no private socket/TLS implementation and no curl fallback. The generic transport needs to support caller-supplied headers; this is the same underlying seam already exposed by the Reddit and Stripe checkpoints.

The remaining named holes are intentionally visible:

- file input;
- Online Payments JSON decoding;
- environment access;
- UUID request-id generation;
- authenticated ICU GET with caller-supplied headers.

Do not replace these with a hidden untyped implementation merely to make the checkpoint green.

## Manual receipt

Run:

```text
ysh check
```

or:

```text
IDRIC=/opt/Idric/build/exec/idris2 ysh check
```

The runner emits only:

```text
PASS checkpoint
FAIL checkpoint
SKIP checkpoint
```

A focused failure at a named hole is useful evidence of the remaining compiler/library boundary.

## Checkpoint ladder

1. source parses/checks;
2. `version` prints `2.19.0`;
3. `endpoints` prints the byte-stable 16-operation inventory;
4. `url payment ID` prints the exact mock v2 URL;
5. `fixture` reads the synthetic file;
6. `fixture` decodes a payment response and matches `expected.tsv` byte-for-byte;
7. `payment` reads the bearer token and merchant ID from the environment;
8. request-id generation produces a fresh value;
9. ICU sends Authorization, merchant-id, request-id, and Accept headers;
10. live mock payment retrieval uses the same TSV contract as the fixture;
11. add request-id lookup forms for payments/captures/refunds/verifications/fraud checks;
12. add mutating commands only after request bodies, consequence-specific verbs, and duplicate-request behavior have fixtures and tests.

See `SURFACE.md` for the audited endpoint list and sequencing.
149 changes: 149 additions & 0 deletions checkpoints/jpmorgan/SURFACE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# J.P. Morgan Online Payments API surface pass

Audit baseline: 2026-09-06.

Online Payments API specification release observed in the official changelog: `2.19.0` (2026-08-04).

This inventory is for the **Online Payments API only**. Checkout, Disputes, Wallet Decryption, Merchant Configuration, Treasury, Embedded Payments, and the other J.P. Morgan Payments APIs are separate surfaces and are not silently mixed into this client.

Canonical references:

- API reference: https://developer.payments.jpmorgan.com/api/home
- Online Payments overview: https://developer.payments.jpmorgan.com/api/commerce/online-payments/overview
- Online Payments changelog: https://developer.payments.jpmorgan.com/api/commerce/online-payments/online-payments/changelog
- Online Payments response codes: https://developer.payments.jpmorgan.com/api/commerce/online-payments/online-payments/error-codes
- OAuth authentication: https://developer.payments.jpmorgan.com/api/commerce/online-payments/oauth-authentication
- Quick start: https://developer.payments.jpmorgan.com/docs/quick-start
- authorize/capture guide: https://developer.payments.jpmorgan.com/docs/commerce/online-payments/capabilities/online-payments/how-to/auth-and-capture-payment
- refund guide: https://developer.payments.jpmorgan.com/docs/commerce/online-payments/capabilities/online-payments/how-to/refund-payment
- verification guide: https://developer.payments.jpmorgan.com/docs/commerce/online-payments/capabilities/online-payments/how-to/verify-payment
- fraud-score guide: https://developer.payments.jpmorgan.com/docs/commerce/online-payments/capabilities/online-payments/how-to/fraud-scores

## Wire contract

The documented mock major-version base is:

```text
https://api-mock.payments.jpmorgan.com/api/v2
```

J.P. Morgan documents Online Payments versioning in the URL prefix (`v2`). The product's specification has its own release number; the latest changelog entry in this pass is `2.19.0`.

The Quick Start request carries JSON and uses OAuth bearer authentication plus merchant and request identifiers:

```text
Accept: application/json
Content-Type: application/json
Authorization: Bearer ACCESS_TOKEN
merchant-id: MERCHANT_ID
request-id: REQUEST_ID
minorVersion: ...
```

The first read-only checkpoint does not acquire OAuth tokens itself. Keep client credentials/private keys outside source. `JPMORGAN_ACCESS_TOKEN` supplies an already-issued bearer token and `JPMORGAN_MERCHANT_ID` supplies the processing merchant identifier.

## Complete Online Payments endpoint inventory

The current surface pass yields 16 HTTP operations across payments, captures, refunds, verifications, and fraud checks.

| Method | Path | Meaning | First CLI phase |
| --- | --- | --- | --- |
| `POST` | `/payments` | Create/authorize a payment; capture can be immediate depending on request | later write |
| `GET` | `/payments` | Retrieve a payment by `requestId` query parameter | read |
| `GET` | `/payments/{id}` | Retrieve a payment by transaction ID | first live read |
| `PATCH` | `/payments/{id}` | Update a payment; documented uses include incremental authorization, reversal/void, and reauthorization | later write |
| `POST` | `/payments/{id}/captures` | Capture a previously authorized payment; supports split/multiple capture cases | later write |
| `GET` | `/captures` | Retrieve capture/payment details by `requestId` | read |
| `GET` | `/captures/{id}` | Retrieve capture/payment details by transaction ID | read |
| `POST` | `/refunds` | Create full, partial, standalone, or capture-related refund | later write |
| `GET` | `/refunds` | Retrieve a refund by `requestId` | read |
| `GET` | `/refunds/{id}` | Retrieve a refund by transaction ID | read |
| `POST` | `/verifications` | Verify a payment instrument | later write-like request, no money movement |
| `GET` | `/verifications` | Retrieve verification details by `requestId` | read |
| `GET` | `/verifications/{id}` | Retrieve verification details by transaction ID | read |
| `POST` | `/fraudcheck` | Request a fraud score/check | later request |
| `GET` | `/fraudcheck` | Retrieve fraud-check details by `requestId` | read |
| `GET` | `/fraudcheck/{id}` | Retrieve fraud-check details by transaction ID | read |

The no-network `jpmorgan endpoints` command emits exactly this operation set in machine-friendly TSV form.

## Identifier model

Do not collapse J.P. Morgan's identifiers into one generic `id` in the normalized model. Important values include:

- `transactionId` — identifies a payment/refund/verification/fraud transaction and is used by path retrieval forms;
- `requestId` — caller/request identifier, also usable to retrieve several resource types through query forms;
- `paymentRequestId` — groups payment request state;
- `authorizationId` — identifies an authorization;
- `captureId` — identifies a capture;
- `refundId` — identifies a refund where present;
- `networkTransactionId` — network-side identifier, not interchangeable with J.P. Morgan's transaction ID;
- `merchantOrderNumber` — merchant business/order reference.

The first fixture keeps `transactionId` and `requestId` separate. Later capture/refund fixtures should preserve their nested identifiers rather than flattening them into one opaque string.

## Response model

The Quick Start payment response exposes a useful stable diagnostic spine:

```text
transactionId
requestId
transactionState
responseStatus
responseCode
responseMessage
amount
currency
```

The first TSV contract uses all except the human-readable response message. Keep the integer amount intact; currency-specific decimal presentation belongs above the wire model.

`transactionState` and `responseStatus` answer different questions. The former describes transaction lifecycle state; the latter reports the request/business result (`SUCCESS`, `DENIED`, or `ERROR`). Do not merge them into one status field.

## Read side first

The first implementation slice is deliberately narrow:

1. print the specification release;
2. print every endpoint/method pair;
3. construct a transaction-ID payment retrieval URL;
4. decode a synthetic payment response;
5. retrieve one payment from the mock environment using an already-issued token.

Then add the other GET forms before implementing payment mutations. This exercises URL construction, OAuth headers, request IDs, JSON decoding, and stable CLI output without accidentally creating or moving money.

## Mutation boundary

The write/request surfaces are not interchangeable generic POSTs:

- `POST /payments` may authorize and/or capture money;
- `PATCH /payments/{id}` can alter an existing authorization, including reauthorization and reversal/void cases;
- `POST /payments/{id}/captures` completes all or part of a manual authorization and can participate in multiple-capture shipment flows;
- `POST /refunds` can return captured funds and has full, partial, standalone, and multi-capture cases;
- `POST /verifications` checks a payment instrument without being a payment;
- `POST /fraudcheck` asks for a fraud decision/score rather than processing the payment itself.

Give each one a named CLI verb and typed request model. Do not expose a primary `post PATH JSON` interface that erases the consequence differences.

`request-id` is also part of duplicate-request handling, so mutation support needs explicit tests for retry/duplicate behavior before it is treated as safe.

## Expansion order

1. Endpoint inventory and exact URL construction.
2. Synthetic payment retrieval fixture.
3. Live mock `GET /payments/{id}` through ICU/Idric-Net.
4. `GET /payments?requestId=...`.
5. Capture GET forms and capture-specific fixture.
6. Refund GET forms and refund-specific fixture.
7. Verification GET forms and fixture.
8. Fraud-check GET forms and fixture.
9. Shared OAuth/merchant/request-id header construction.
10. Typed request bodies for `POST /verifications` and `POST /fraudcheck`.
11. `POST /payments` only in mock/test usage with duplicate-request receipts.
12. `POST /payments/{id}/captures` with full/partial/multiple-capture fixtures.
13. `PATCH /payments/{id}` with separate fixtures for each supported update intent.
14. `POST /refunds` with full/partial/standalone/multi-capture fixtures.
15. Production base/configuration only after the client-specific environment contract is known; do not guess production endpoints from the mock hostname.

Each resource follows the same receipt pattern: exact URL and headers, synthetic fixture, byte-stable output, mock/live transport, then consequence-specific write tests.
57 changes: 57 additions & 0 deletions checkpoints/jpmorgan/check
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env ysh

# Manual Idriç J.P. Morgan Online Payments checkpoint runner.
# Deliberately not part of the root make test while named holes remain.

set -u

HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
IDRIC=${IDRIC:-idris2}

TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT HUP INT TERM

status=0

available() {
case "$1" in
*/*) test -x "$1" ;;
*) command -v "$1" >/dev/null 2>&1 ;;
esac
}

pass() {
printf 'PASS\t%s\n' "$1"
}

fail() {
printf 'FAIL\t%s\n' "$1"
status=1
}

skip() {
printf 'SKIP\t%s\n' "$1"
}

show_diagnostics() {
for path in "$@"; do
if test -s "$path"; then
sed 's/^/ /' "$path"
fi
done
}

if ! available "$IDRIC"; then
skip "idric (not found: $IDRIC)"
exit 0
fi

if "$IDRIC" --check "$HERE/idric/JPMorgan.idric" \
>"$TMP/idric" 2>"$TMP/idric.err"; then
pass 'idric/check'
else
fail 'idric/check'
show_diagnostics "$TMP/idric" "$TMP/idric.err"
fi

exit "$status"
2 changes: 2 additions & 0 deletions checkpoints/jpmorgan/fixture/expected.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
transaction_id request_id state status code amount currency
11111111-2222-4333-8444-555555555555 aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee CLOSED SUCCESS APPROVED 1000 USD
Loading
Loading