/

to search

Introducing Setu Changelog Check it out ↗

#iOS integration

Setu provides ready to use URLs for iOS integration. Contact Setu to update your logo, colours, fonts as per your branding. You can reach out to billpay.support@setu.co for any further clarifications. This quickstart page provides the sample code for the following specs—

  • Programming language — Swift 5.* (Latest version 5.3)
  • Interface — Storyboard
  • Life Cycle delegation — UI Kit
  • iOS versions supported — 12+ (Latest version 14.4)

This quickstart provides the integration guidelines for iOS integration with Setu’s default UPI payment option. If you’d like to use your own payment gateway, please refer to this guide instead.


#Step 1 — Implement web view in your app

The following steps need to be taken for webview integration—

  1. Get link from the backend
  2. Open a webview and attach the iOS interface

Get link from the backend

This step gives a one time Setu URL to be used by your customer for the bill fetch or payment flow. The Create link API needs to be called when the iOS app wants to obtain a one time link to load Setu’s screen flow inside a webview.

None of the parameters aside from mobile number are mandatory, but depending on what is passed the returned link will display different UI.


You can have the following scenarios, depending on what you choose to send along with the customer’s mobile number—

  • If no other input is passed, it will take the user to the home page with all BBPS categories.
  • If category code is passed, it will show user a list of billers in that category.
  • If category code and biller ID is passed, it will show the bill fetch form where a customer can enter their identifers (biller specified parameters)
  • If the category code, biller ID and parameters are passed, it will show the bill directly.

All query parameters should be url-encoded to escape special characters


The above request will return URL based on the input params. Here’s a sample—

{
"link": "https://billpay-qa.setu.co/1238993883748223",
"sessionId": "1238993883748223",
"success": true,
"traceId": "GHSUU99128DBVU"
}

Switch control from your app to Setu

The link returned by the API should be loaded within a WKWebView, facilitated by SwiftUI's WebView. ContentView controls the main view, which incorporates navigation controls and a custom back button. WebViewCoordinator manages navigation actions and delegates for smooth interaction with web content.

If you’re using a cross platform solution—like Flutter, React Native, Ionic—look at the code snippets provided here.

Here’s a sample code for the same -

import SwiftUI
import WebKit
struct ContentView: View {
var body: some View {
NavigationView {
WebView(urlString: "https://billpay.setu.co/1234") // Replace with the actual URL
.navigationBarItems(leading: WebViewBackButton())
.onAppear {
NotificationCenter.default.addObserver(forName: Notification.Name("GoBack"), object: nil, queue: .main) { _ in
WebViewCoordinator.shared.goBack()
}
}
}
}
}
struct WebViewBackButton: View {
var body: some View {
Button(action: {
NotificationCenter.default.post(name: Notification.Name("GoBack"), object: nil)
}) {
Text(Image(systemName: "chevron.left"))
}
}
}
class WebViewCoordinator: NSObject, ObservableObject, WKNavigationDelegate, WKScriptMessageHandler {
static let shared = WebViewCoordinator()
var webView: WKWebView?
func goBack() {
webView?.goBack()
}
// Handle navigation actions, including opening "upi" or "phonepe" URLs
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url, ["upi", "phonepe"].contains(where: { url.absoluteString.contains($0) }) {
UIApplication.shared.open(url)
decisionHandler(.cancel)
} else {
decisionHandler(.allow)
}
}
}
struct WebView: UIViewRepresentable {
let urlString: String
@EnvironmentObject var coordinator: WebViewCoordinator
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.navigationDelegate = context.coordinator
// Register script message handler
webView.configuration.userContentController.add(context.coordinator, name: "ios_observer")
context.coordinator.webView = webView
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
if let url = URL(string: urlString) {
uiView.load(URLRequest(url: url))
}
}
func makeCoordinator() -> WebViewCoordinator {
WebViewCoordinator.shared
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(WebViewCoordinator.shared)
}
}
#endif

Here is a sample of the Swift class designed to handle the unload event

// Setup to handle messages from JavaScript
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "ios_observer", let messageBody = message.body as? [String: String] {
if messageBody["function"] == "unload" {
handleUnload()
}
}
}
private func handleUnload() {
// logic to close webview and return to app
}

The class will contain 1 method—

  • unload This should be used by the your app to dismiss the webview.

Special use case: This unload function can also be used for dismissing the webview and redirecting a user back to your native app once a bill payment journey is completed (i.e. payment is successful) via a CTA from the Setu webview. Please let our team know if you would like to enable this use case for your app.


#Step 2 — Optionally configure webhook

You may optionally want to listen to user events—like successful or failed bill fetch, bill payment status and more—through webhooks. Refer to this guide for more information.


#Step 3 — Get Production credentials and go live Once you are done testing your

integration, ensure that all KYC and legal agreements are submitted. Contact Setu for getting enabled on production.


Was this page helpful?