Skip to content

feat: add UPI Intent payment instrument and credential schemas#313

Open
paraskathuria-dev wants to merge 1 commit intoUniversal-Commerce-Protocol:mainfrom
paraskathuria-dev:feat/upi-intent-payment-instrument
Open

feat: add UPI Intent payment instrument and credential schemas#313
paraskathuria-dev wants to merge 1 commit intoUniversal-Commerce-Protocol:mainfrom
paraskathuria-dev:feat/upi-intent-payment-instrument

Conversation

@paraskathuria-dev
Copy link
Copy Markdown

Summary

Introduces the upi_intent payment instrument and credential types, formalizing UPI Intent deep link payments in UCP. UPI (Unified Payments Interface) is India's real-time payment rail processing 14+ billion monthly transactions. This contribution enables businesses to offer UPI Intent payments within UCP's existing escalation mechanism.

What's Added

  • source/schemas/shopping/types/upi_intent_instrument.json — A new instrument type where type: "upi_intent" signals to the platform that payment will be completed via an NPCI-compliant deep link. Extends payment_instrument.json via allOf. Includes optional display_name and display_logo for platform UI. No app constraints are supported — per NPCI mandate, the device OS presents the UPI app chooser and platforms must not filter or target specific apps.

  • source/schemas/shopping/types/upi_intent_credential.json — A transaction-specific credential returned by the business inside a requires_escalation response. Contains the NPCI-compliant intent_uri (validated via pattern), transaction_reference (maps to NPCI tr, max 35 chars), optional qr_code_data (base64 PNG/SVG for desktop fallback), qr_code_string, and expires_at (ISO 8601 expiry). Extends payment_credential.json via allOf.

  • docs/specification/examples/upi-intent-payment-handler.md — Full handler spec for com.razorpay.upi_intent demonstrating the pattern end-to-end: business prerequisites, handler config, instrument advertising, Complete Checkout → escalation flow, Razorpay Orders API integration, NPCI intent URI construction with RFC 3986 encoding rules, platform decision matrix (Android native / mobile web / iOS / desktop), HMAC-SHA256 webhook signature verification, polling protocol, and security considerations.

  • mkdocs.yml — Navigation and llmstxt entries under Payment Handler Examples.

Why This Is Needed

UPI Intent differs fundamentally from UCP's card-centric credential exchange model:

  • No card networks — payment flows directly between bank accounts via NPCI infrastructure
  • No stored credentials — each transaction uses a one-time intent URI; no tokenization required
  • Device-native app selection — the OS presents the UPI app chooser (GPay, PhonePe, Paytm, BHIM, and 200+ bank apps); platforms must not control app choice per NPCI mandate
  • QR code fallback — for desktop/web contexts where upi:// cannot be launched

Businesses have been implementing this ad-hoc with no standardized escalation signal. This contribution formalizes the pattern using the existing requires_escalation mechanism — no new platform behavior is required.

Design Decisions

Schema extension pattern: Both new schemas extend the base types via allOf, consistent with card_payment_instrument.json and token_credential.json. The base schemas (payment_instrument.json, payment_credential.json) are intentionally left unchanged — they use additionalProperties: true to preserve UCP's open/extensible architecture.

No app constraints: Unlike card_payment_instrument.json which supports brand constraints, upi_intent_instrument.json intentionally omits constraints. The NPCI mandate requires all platforms to use implicit/generic intent calls; explicit app targeting violates compliance requirements.

Credential carries the intent URI: The instrument is intentionally minimal (just the type discriminator + display metadata). The transaction-specific intent_uri is generated server-side by the business/PSP and returned in the credential inside the requires_escalation response — consistent with how hosted checkout providers work.

Type discriminator: type: const: "upi_intent" follows the same discriminator pattern used by card_payment_instrument (type: const: "card").

Validation Checklist

  • Schemas validate as valid JSON (JSON.parse clean)
  • Both schemas conform to JSON Schema draft 2020-12
  • allOf references resolve correctly against base schemas
  • type discriminator uses const for unambiguous resolution
  • Field names follow UCP snake_case convention
  • intent_uri pattern validates NPCI-compliant upi://pay?...pa= format
  • transaction_reference pattern enforces NPCI max 35 alphanumeric chars
  • qr_code_data pattern validates base64 data URI format (PNG or SVG)
  • All display URIs enforce HTTPS
  • No secrets or sensitive values in any schema or doc
  • Handler example follows the Payment Handler Guide structure
  • mkdocs.yml navigation and llmstxt entries added

References


Contributed by Razorpay · Apache 2.0

Introduces two new JSON Schema types and a complete handler example for
UPI Intent — India's device-native bank-to-bank payment method processed
over the NPCI UPI rail (14+ billion monthly transactions).

## New Schemas

- `source/schemas/shopping/types/upi_intent_instrument.json`
  A payment instrument type for UPI Intent deep link payments. Extends
  `payment_instrument.json` via `allOf` with `type: const: "upi_intent"`
  as the discriminator. Includes optional `display_name` and
  `display_logo` fields for platform UI rendering. No app constraints are
  supported — per NPCI mandate, the device OS presents the app chooser
  (Google Pay, PhonePe, Paytm, BHIM, etc.) and platforms must not
  filter or target specific UPI apps.

- `source/schemas/shopping/types/upi_intent_credential.json`
  A transaction-specific credential containing an NPCI-compliant intent
  URI and optional QR code for desktop/web fallback. Extends
  `payment_credential.json` via `allOf`. Required fields: `intent_uri`
  (validated against NPCI `upi://pay?...pa=` pattern) and
  `transaction_reference` (maps to NPCI `tr` parameter, max 35 chars).
  Optional: `qr_code_data` (base64 PNG/SVG), `qr_code_string`, and
  `expires_at` (ISO 8601 expiry timestamp).

## New Example Handler

- `docs/specification/examples/upi-intent-payment-handler.md`
  A complete handler specification for `com.razorpay.upi_intent`
  demonstrating the UPI Intent pattern end-to-end: handler config
  schema, instrument advertising, Complete Checkout → escalation flow,
  Razorpay Orders API integration, NPCI intent URI construction with
  RFC 3986 encoding rules, platform decision matrix (Android/iOS/desktop),
  HMAC-SHA256 webhook signature verification, polling protocol, and
  security considerations.

## Why This Is Needed

UPI Intent differs fundamentally from UCP's card-centric credential
exchange model:
- No card networks — payment flows directly between bank accounts via NPCI
- No stored credentials — each transaction uses a one-time intent URI
- Device-native app selection — the OS presents available UPI apps
- QR code fallback — for desktop/web contexts

This contribution formalizes the UPI Intent escalation pattern using the
existing UCP `requires_escalation` mechanism. Platforms that already handle
`requires_escalation` support this handler with no additional protocol changes.

## Design Notes

Both new schemas extend base types via `allOf`, consistent with the existing
`card_payment_instrument.json` and `token_credential.json` patterns. The base
schemas (`payment_instrument.json`, `payment_credential.json`) are intentionally
left unchanged, preserving UCP's open/extensible architecture.

Contributed by: Razorpay (razorpay.com) · Apache 2.0
@google-cla
Copy link
Copy Markdown

google-cla bot commented Mar 27, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant