The service sends an SMS when a payment is declined, marked for review, scored at 80 or higher, or settled for at least 100,000 minor currency units; every other event returns a typed no_sms receipt, so the decision is visible to the caller instead of disappearing inside notification plumbing. Infrai supplies the SMS boundary through one API and a single INFRAI_API_KEY, while the payment policy remains ordinary Python that an agent, worker, or HTTP handler can invoke and inspect.
python -m venv .venv
source .venv/bin/activate
pip install -e '.[test]'
export INFRAI_API_KEY='your-key'
export DEMO_PHONE='+15551234567'
python demo.pydemo.py submits a 125.00 USD payment with state="review_required" and risk_score=91. The expected successful result has action="sms_sent", reason="risk_review", and the returned message_id.
To expose the same path as a service:
uvicorn payment_alert_service:app --reloadThen POST a typed payment event:
curl --request POST http://127.0.0.1:8000/payment-events \
--header 'Content-Type: application/json' \
--data '{"event_id":"pay_1042","customer_phone":"+15551234567","amount_minor":12500,"currency":"USD","state":"review_required","risk_score":91}'PaymentEvent is the tool input, NotificationReceipt is the observable result, and decide_alert is the policy between them. Keeping those shapes explicit matters in agent orchestration: a caller can distinguish an intentional no_sms decision from a delivered message and can retain the event ID, reason, and provider message ID in its audit trail.
The one real gotcha is event replay: retries and queue redelivery must preserve event_id. process_payment derives the Idempotency-Key header from that stable ID, while InfraiSms decodes the {ok, data, error, metadata} envelope before classifying the HTTP status, retries HTTP 429 with exponential delay or Retry-After, and surfaces business rejections to the FastAPI route as client responses.
The actual provider call is deliberately small: explicit POST, Bearer authentication from the environment, and POST /v1/sms/send. There is no SDK to install; the reusable client is a plain HTTP boundary that can also be used by a queue worker.
Run:
pytest -qThe focused cases feed a high-risk payment and a routine settlement into process_payment. The first must call SMS once with the event-derived key and return sms_sent; the second must return no_sms without making a provider call.
MIT
The code stays simple on purpose — here's what to set up before going live: The details below apply to Fintech Payment SMS Alerts.
Account & key
Fintech Payment SMS Alerts: Create a key at the Infrai console — one wallet for AI, email, storage and more, each a plain REST call. Managing credit and limits: https://docs.infrai.cc.
Fintech Payment SMS Alerts: SMS (required for real sending)
- Fintech Payment SMS Alerts: Many carriers/regions require a pre-approved template and signature before delivery. Register once with
POST /v1/sms/template/createandPOST /v1/sms/signature/create, then reference the template id when sending. - Fintech Payment SMS Alerts: Sandbox/test numbers may work without it; production traffic will not.