The Zennopay iOS SDK is a thin, dependency-free wrapper that hands a payment intent off to the Zennopay-hosted checkout. Modeled on the Stripe Checkout pattern, it opens the checkout URL in a system browser tab viaDocumentation Index
Fetch the complete documentation index at: https://docs.zennopay.in/llms.txt
Use this file to discover all available pages before exploring further.
ASWebAuthenticationSession — the user always sees a real URL bar and an
Apple-mediated consent sheet. When checkout completes, the browser redirects
back to your app via a registered URL scheme and the SDK surfaces a typed
PaymentResult.
Requirements
- iOS 13.0+
- Swift 5.9+
- Xcode 15+
- Only
Foundation+AuthenticationServices— no third-party dependencies
Install via Swift Package Manager
In Xcode: File → Add Package Dependencies… and paste the repository URL:0.1.0, then add the
Zennopay library product to your app target.
If you maintain your own Package.swift, declare:
"Zennopay" to your target’s dependencies.
Register a URL scheme
The SDK delivers the payment result by redirecting from the checkout web to a URL scheme your app owns. Register it in yourInfo.plist:
yourapp://payment-result?intent_id=...&status=.... You do not need to
handle it in SceneDelegate / AppDelegate —
ASWebAuthenticationSession captures the callback before it reaches the OS
routing layer and delivers it directly to the SDK’s completion handler.
Quickstart
Async / await
Result + status
.pending means the checkout web could not synchronously confirm the
outcome (async settlement, payment-network review, etc.). Your backend
should poll the intent or wait for a webhook for the final state.
Error handling
| Case | Meaning |
|---|---|
intentMismatch | The JWT’s zennopay:intent_id claim does not match the intentID you passed to openCheckout. Caught client-side before the browser opens. |
jwtExpired | The JWT’s exp is in the past (30-second clock-skew tolerance). Mint a fresh token from your backend and retry. |
malformedToken | The JWT is not three segments, the base64 doesn’t decode, or the payload isn’t a JSON object. |
invalidIssuer | Reserved for parity with the Android SDK; on iOS, missing-claim cases surface as jwtMissingClaim. |
How it works
- Your backend exchanges its Zennopay API key for a short-lived JWT scoped
to one
intent_id. - Your app calls
Zennopay.openCheckout(...)with that JWT. - The SDK verifies the JWT’s
zennopay:intent_idclaim matches theintentIDargument before opening the browser. Mismatch raisesZennopayError.intentMismatchsynchronously. - The SDK opens
https://checkout.zennopay.com/flow/{intent_id}/scan#token={jwt}inASWebAuthenticationSession. The token rides in the URL fragment (after#), so it never reaches the HTTP server in logs or proxies. - The user completes (or cancels) checkout in the system browser.
- The checkout web redirects to
yourapp://payment-result?intent_id=...&status=.... - The SDK parses the redirect and calls your completion handler with a
PaymentResult(or aZennopayError).