Project

General

Profile

Edit Copy Actions

Feature #3933

closed

Payment Initiation for Zelle Payment

Added by Anonymous 11 months ago. Updated 8 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Start date:
09/14/2025
Due date:
% Done:

40%

Estimated time:
192:00 h
Spent time:

Description

General:
We are developing Payment Initiation feature for sending and receiving payments through a Zelle-connected bank partner behind a Payments API.
The following components are planned as part of this feature.
Payment Orchestrator
Bank Client (httpx)
Webhook Receiver (FastAPI)
Observability
> payment_id and client_ref across logs.
> Status metrics (initiated, completed, returned, retry counts, webhook latency).


Add

Subtasks


Add

Related issues

Updated by Anonymous 11 months ago

Please add estimated time

Updated by Yogeesh sai 11 months ago

  • Estimated time set to 192:00 h

Payment Orchestrator Implementation: 2 days
Bank Client (httpx) Setup: 1 day
Webhook Receiver (FastAPI): 1.5 days
Observability (logging + metrics): 1.5 days
Integration & Testing (end-to-end flow): 2 days
Total Estimated Time:8 days (full cycle from development → testing → ready for QA).

Updated by Yogeesh sai 11 months ago

  • % Done changed from 0 to 40

Customer → POS → Generates TX1234 & shows Zelle info

Customer sends Zelle payment

Plaid polls → Bank → New transaction (Zelle, $25.00, TX1234)

Backend checks → Match found → POS: "Payment Confirmed"

Updated by Yogeesh sai 11 months ago

Client App → Payments API → Payment Orchestrator

Bank Client (httpx → Bank Partner API)

Bank Partner (Zelle rails)

Counterparty Bank/Zelle

Webhook Receiver (FastAPI)

Payment Orchestrator (update status)

Observability (metrics + logs)

Updated by Yogeesh sai 10 months ago

1. Payment Orchestrator

Role: Central brain for initiating and managing payments.

Responsibilities:

Accepts a payment initiation request (e.g., {amount, recipient, client_ref}).

Generates a payment_id (UUID).

Calls Bank Client to send payment to partner bank’s API.

Tracks lifecycle states: initiated → processing → completed/returned.

Handles retries (e.g., if partner bank API is down).

Persists state to database (payments table).

2. Bank Client (httpx)

Role: Abstraction over the partner bank’s Payments API.

Responsibilities:

Handle auth (OAuth2, mTLS, API key depending on Chase/partner requirements).

Send payment initiation requests via HTTP.

Map responses to internal schema (payment_id, status, bank_ref).

Include resiliency: timeout, retries, circuit breaker (httpx supports retries).

Example:

async with httpx.AsyncClient() as client:
resp = await client.post(
bank_url + "/payments",
headers={"Authorization": f"Bearer {token}"},
json=payload
)

3. Webhook Receiver (FastAPI)

Role: Handle async notifications from bank/Zelle (e.g., payment completed, returned).

Responsibilities:

Expose /webhook/payments.

Verify auth/signature from partner bank.

Parse payload and update local DB (payment_id, status, timestamps).

Ack quickly with 200 OK.

Queue heavy processing (e.g., ERP updates) to async workers.

Example (FastAPI):

from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/webhook/payments")
async def payment_webhook(req: Request):
body = await req.json()
payment_id = body["payment_id"]
status = body["status"] # Update DB with new status
return {"ok": True}

4. Observability

Logs:

Every log line includes payment_id and client_ref.

Example:

{"level":"info","payment_id":"1234","client_ref":"INV-1002","msg":"Payment initiated"}

Metrics (Prometheus / OpenTelemetry):

payment_status_total{status="initiated"}

payment_status_total{status="completed"}

payment_status_total{status="returned"}

payment_retry_count{payment_id="1234"}

payment_webhook_latency_seconds{}

Tracing (OpenTelemetry + Jaeger/Tempo):

Trace spans: PaymentOrchestrator → BankClient → WebhookReceiver.

Propagate payment_id + client_ref as trace attributes.

🔹 Payment Lifecycle Example

Initiation:
Client → Orchestrator → Bank Client → Bank API → initiated.
Log: {"payment_id":"123","status":"initiated"}

Webhook:
Bank → Webhook Receiver → DB update → Orchestrator marks completed.
Log: {"payment_id":"123","status":"completed"}

Metrics:

payment_status_total{status="initiated"}++

Later payment_status_total{status="completed"}++

Webhook latency recorded.

🔹 Suggested Tech Stack

FastAPI → Orchestrator + Webhook service.

httpx → Bank client.

SQLAlchemy / Postgres → Persistence for payments.

Celery / RQ → For async retries & background jobs.

Prometheus + Grafana → Metrics.

OpenTelemetry + Jaeger → Tracing.

Structured JSON logging → For correlation.

Actions #6

Updated by Yogeesh sai 10 months ago

  • Status changed from New to Resolved
Actions #7

Updated by Yogeesh sai 8 months ago

  • Status changed from Resolved to Closed
Edit Copy Actions

Also available in: Atom PDF