Wallets (Vipps, Swish, MobilePay) Integration

Pia SDK supports Vipps, Swish and MobilePay wallets with a straightforward and easy integration. App-switch to and from the wallet apps is handled by the SDK covering all UX scenarios and corner cases from start to finish. A single declarative API is used to initiate a wallet payment process with callbacks for payment registration, redirect and failure invoked by the SDK.

In order to initiate a wallet payment:

/// Initiating a wallet-payment. Returns `false` if the wallet app cannot be opened; 
/// It not installed or your app is missing URL scheme in info.plist for the wallet-app.
/// 
/// paymentProcess: Identifies the wallet process. 
/// walletURLCallback: Callback with `walletURL` obtained from registration request
///                    with merchant backend. Callback with error if unsuccessful
/// redirectWithoutInterruption: Callback with value `true` if app-switch was successful.
/// failure: Callback notifying failure typically to launch the wallet app. Contains `error` for details. 
///
let canLaunch = PiaSDK.launchWalletApp(
    for: PaymentProcess.walletPayment(.vipps / .vippsTest / .swish / .mobilePay),
    walletURLCallback: self.registerWalletPayment(callback:), // see registration section
    redirectWithoutInterruption: self.walletAppDidRedirect(withoutInterruption:), // see redirect handling section
    failure: self.walletDidFail(withError:) // see error handling section
}

if !canLaunch { /* Wallet app is not installed, preferably lead user to other payment methods */ }

Wallet App Detection

The launchWalletApp wallet API, returns nil if the wallet app cannot be launched.

The SDK checks this as the first step in the process preventing unnecessary payment registration. If the wallet app is not installed on user’s device, we recommend leading user to other available payment methods. On the other hand, the SDK returns wallet app not installed error in the corner case where user uninstalls the wallet app after payment has been registered with merchant backend.

In order for the PiA SDK to perform app detection, you need to the wallet app schemes (shown below) under the LSApplicationQueriesSchemes key in your Info.plist file. If you skip this step, the PiA SDK will always return wallet app cannot open error even though Vipps app is installed on the device.

Vipps

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>vipps</string>
    <string>vippsMT</string>
</array>

Swish

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>swish</string>
</array>

MobilePay

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>mobilepayonline</string>
    <string>mobilepayonline-test</string>
</array>

Wallet Payment Registration

Register the wallet payment with your merchant backend in order to obtain a walletURL which the SDK uses to launch the wallet app. Regardless of success or failure when making registration request with your merchant backend, make sure to callback the SDK with success or failure results. The following shows an example of these callbacks:

func registerWalletPayment(callback: @escaping (WalletRegistrationResponse) -> Void) {

    // Make registration API call to your backend to obtain `walletURL`
    // redirectURL should have this format - "your_app_scheme://piasdk?wallet=walletName" (walletName = vipps/swish/mobilepay)
    callback(.success(withWalletURL: walletURl))

    // If unsuccessful, notify SDK with an error object
    callback(.failure(error)) 
}

Note : Vipps and Mobilepay support AUTH+CAPTURE process. If autoSale is set to “true”, Netaxept authorizes and immediately captures the amount set in the REGISTER call. It is optional and default value is false (authorization only and capture from the backend with additional process call).

Vipps Payment Registration

In case of Vipps, user’s phone number is an optional parameter. If you choose not to pass the phone number, you need to additionally pass the isApp = true parameter in the registration request body. If choosing to pass user’s phone number, use the following format: (Norwegian prefix): phoneNumber = +4711111111. Netaxept REST API expects URL encoded phone number. The encoding can take place in the client or merchant backend.

Wallet App Redirect

All redirects to your application are received in AppDelegate open URL delegate method. Notify the SDK of a wallet app redirect as follows:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    guard !PiaSDK.willHandleRedirect(with: url, andOptions: options) else {
        // SDK has handled the redirect and will invoke the `redirect` callback explained below
        return
    }

    // This was not a wallet app redirect, handle accordingly

    return true
}

Use the redirectWithoutInterruption: (Bool) -> Void callback to handle successful redirect or potentially interruption caused by user manually returning to your app. See example below:

func walletAppDidRedirect(withoutInterruption successfulRedirect: Bool) {
    // `successfulRedirect` is false incase of interruptions

    // Make a query request to your backend to check payment status. 
    // and commit/rollback the transaction accordingly. 

    // Scenarios:

    if successfulRedirect { Wallet app redirected to your app }
    else {
        // User manually returned to your app after authorizing, declining or 
        // possibly without any action at the wallet app. 
    }

    // Payment status in either case can only be obtained from your merchant backend.
    self.api.commitPayment { result in 

        // Present result to user accordingly 

        // Remove the activity indicator presented by the SDK
        PiaSDK.removeTransitionView()
    }
}

Wallet payments - Cases of interrupted transactions

The typical payment flow via mobile wallets starts from the app where transaction registration request is sent to merchant backend. Upon receiving a wallet URL, the SDK launches the wallet app. The wallet app then redirects back to the application and PiaSDK notifies the associated wallet payment delegate to complete the transaction.

However,

  • User may interrupt this flow e.g. by manually navigating to your application before completing authorization at the wallet app or
  • The wallet app may fail to redirect for an unknown reason forcing the user to manually return to your application

In these and related scenarios, PiaSDK notifies interruption through in the callback redirectWithoutInterruption by returning false:

Upon receiving interruption, it’s best to query the transaction status and check if the authorization was complete or has been interrupted/denied in the wallet app. (If the user navigates back to the wallet app for authorization resulting in a successful redirect to your app, PiaSDK will notify the redirect where the app can commit / rollback the transaction accordingly)

Error Handling

The last callback in the wallet API is dedicated to error handling - failure: (WalletError) -> Void. In most cases, failing to launch a wallet app is communicated in the return value of the launch API - let canLaunch = PiaSDK.launchWalletAp(…). However, in the corner cases where user uninstalls the wallet app after the process has started, the SDK invokes this failure callback.

Here are the 2 scenarios where a failure callback might be invoked (and one more scenario specific to MobilePay):

  • Invalid walletURL: Indicates failure to launch the wallet app with given walletURL. Check the validity of this URL returned from your merchant backend.
  • Wallet App Not Installed: Lead user to a different payment method.
  • Network Error - Specific to MobilePay: Indicates network issues while attempting to launch MobilePay. Remind user to check their network connection or optionally lead to a different payment method.

Additional Settings

The SDK presents an activity indicator in the transitions to and from a wallet app. A root view of your application (UIApplication.shared.rootViewController.view) is used to display the activity indicator simultaneously preventing any user interaction.

However, if you choose to replace this activity indicator with your own, use the showsActivityIndicator parameter:

PaymentProcess.walletPayment(for: wallet, showActivityIndicator: false)

In this case, you’re responsible to block user interactions while the wallet payment is in progress.

Vipps Payment Diagram

Here are the flow diagram for Vipps payment:

Vipps Payment Flow

Vipps Flow

Swish Payment Diagram

Here is the flow diagram for Swish payment:

Swish Payment Flow

Swish Flow

MobilePay Payment Diagram

Here is the flow diagram for MobilePay payment:

MobilePay Flow

MobilePay Flow
Netaxept backend integration request body - Vipps payment registration:

You can either pass the phone number or set the isApp to true.

{
    "customerPhoneNumber" : "string" or "isApp" : "true",
    "paymentMethodActionList" : { 
        "PaymentMethod" : "Vipps"
    }
}
Netaxept backend integration request body - Swish payment registration:
{
    "paymentMethodActionList" : { 
        "PaymentMethod" : "SwishM" 
    }
}
Netaxept backend integration request body - Mobilepay payment registration:
{
    "paymentMethodActionList" : { 
        "PaymentMethod" : "Mobilepay" 
    }
}

Note: Netaxept backend integration tips can be found in 5.4 Backend Tips, Register API section