Skip to content

    In-App SDKs

    This is for you who want to use in-App SDK integration.

    Overview

    The sections dedicated to the SDKs are divided by programming language, and contain information relating to the installation of these tools and their use. The SDKs can be modified according to the needs of the developers.

    Below is a list of the SDKs divided by programming language.

    MiA XPay Android SDK is a library which facilitates the embedded XPay Checkout integration in your Android application.

    MiA - XPay iOS SDK is a library which facilitates the integration of the hosted XPay Checkout in your iOS application.

    Through the SDK made available by Nexi, it is possible to choose between the OkHttp client and HttpClient5.

    The SDK may not implement all the solutions made available by the gateway, refer to the dedicated sections to retrieve more information.

    Support

    In case of implementation difficulties or errors returned by the SDKs, please refer to the support section.

    Mobile SDK Manual

    NPG Mobile SDK - Integration Guide

    Platforms: iOS & Android
    Validation status: Technically validated against Android SDK v1.1.0 (.aar)

    Contents

    1. Purpose and scope

    This guide explains how to integrate the NPG mobile SDK into iOS and Android applications and how to use the payment capabilities exposed by the SDK. The Android content has been technically validated against the classes, public method signatures, manifest and resources contained in ngpsdk-release.aar from android-xpay-v1.1.0.zip. The iOS examples are preserved from the supplied source documentation but could not be binary-validated because no iOS framework/package was included in the validation bundle.

    Scope The code samples in this document are based on the SDK interfaces shown in the supplied README. Exact model fields, mandatory attributes, environment values, and backend prerequisites remain defined by the NPG API documentation and the SDK version distributed to the merchant.

    2. Integration overview

    The SDK exposes multiple payment patterns. Choose the pattern that matches the merchant experience and the payment method to be offered.

    CapabilityWhen to use itExperience
    Card VerificationVerify card data using the SDK flow.Native SDK flow
    Payment MethodsRetrieve the payment methods available for the configured merchant/environment.SDK service call
    HPP - URL onlyCreate an HPP order and receive a URL. The host application decides how to open it.Hosted checkout
    HPP - WebViewCreate and display the HPP inside an embedded WebView.Hosted checkout in app
    HPP - In-app browserOpen the HPP in Chrome Custom Tabs or SFSafariViewController.Hosted checkout in secure browser surface
    2-Step PaymentCollect card data using the SDK card form and start the 2-step payment flow.Native card form + SDK flow
    3-Step PaymentCollect card data using the SDK card form and start the 3-step payment flow.Native card form + SDK flow
    MOTOProcess a MOTO request.SDK service flow
    Apple Pay / Google PayUse the wallet-specific native SDK UI and callbacks.Native wallet flow

    Native wallet vs HPP wallet

    The Wallet section of this guide describes native Apple Pay and Google Pay integration through SDK-specific views and callbacks. HPP is a different integration model: the checkout UI is hosted and rendered in a browser surface. If Google Pay is offered inside an Android WebView-based HPP, the WebView itself must also satisfy Google Pay WebView requirements; otherwise Google Pay can fail even when the HPP page is correctly configured.

    3. Getting started

    Add the NPG SDK as a dependency to the mobile application, then initialize a PaymentClient with the environment hostname and the API key provided for the integration. Android SDK v1.1.0 declares minSdkVersion 23. The Android PaymentClient constructor validates the hostname format and requires the API key to match a UUID format; invalid values throw InvalidHostnameException or InvalidApiKeyException.

    iOS

    code

    let ngpclient = PaymentClient(host: host, xApiKey: xApiKey)

    Android

    code

    PaymentClient paymentClient = new PaymentClient(hostname, apiKey);

    Implementation note Do not hard-code production credentials directly in source code. Follow the credential distribution and protection rules defined for your NPG integration. Mobile application packages can be inspected, so any client-side credential must be treated according to its intended security model.

    Recommended application responsibilities

    • Keep environment configuration (test/production host, merchant configuration, feature flags) separate from UI code.

    • Handle success, failure, and user cancellation explicitly for every payment flow.

    • Do not assume a payment is successful only because the UI closes; use the SDK response and the server-side payment state defined by the NPG integration.

    • Avoid logging sensitive payment data, wallet payloads, or credentials.

    • Test lifecycle events, app background/foreground transitions, rotation/recreation on Android, and interrupted authentication flows.

    4. Card verification

    API reference: POST /orders/card_verification

    Use this flow when the application needs to execute the card-verification operation exposed by NPG.

    iOS

    code

    do {
        let req: CardVerificationRequest // initialize the request
        let response = try await ngpclient!.CardVerification(param: req)
        // handle response
    } catch let e as ClientException {
        // handle client error
    } catch let e as UnauthorizedException {
        // handle authentication/authorization error
    } catch let e as ServerErrorException {
        // handle server error
    } catch {
        // handle unexpected error
    }

    Android

    The SDK example uses a request code and returns the result through the Activity result callback.

    code

    Activity activity = this;
    CardVerificationRequest request; // initialize the request
    paymentClient.verifyCard(activity, request, CARD_VERIFICATION_REQUEST_CODE);

    code

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    
        if (data == null) {
            // User cancelled the operation or no result payload is available
            return;
        }
    
        if (requestCode == CARD_VERIFICATION_REQUEST_CODE) {
            showCardVerificationResult(resultCode, data);
        }
    }
    
    private void showCardVerificationResult(int resultCode, Intent data) {
        CardVerificationRequest request =
            (CardVerificationRequest) data.getSerializableExtra("request");
    
        if (resultCode == RESULT_OK) {
            CardVerificationResponse response =
                (CardVerificationResponse) data.getSerializableExtra("response");
            // handle response
        } else {
            Exception exception =
                (Exception) data.getSerializableExtra("exception");
            // handle error
        }
    }

    Android result contract Android SDK v1.1.0 calls startActivityForResult(...) internally from PaymentClient. Handle the corresponding result in onActivityResult(...), using the request code supplied by the merchant application. The SDK returns Serializable extras using the keys request, response and exception in the inspected flows.

    5. Retrieve payment methods

    API reference: POST /payment_methods

    Use this operation to retrieve the payment methods made available by the configured NPG environment and merchant setup. The returned list can be used to decide which payment options to expose in the application.

    iOS

    code

    do {
        let response = try await ngpclient!.GetPaymentMethods()
        // render or use the returned payment methods
    } catch let e as ClientException {
        // handle client error
    } catch let e as UnauthorizedException {
        // handle authentication/authorization error
    } catch let e as ServerErrorException {
        // handle server error
    } catch {
        // handle unexpected error
    }

    Android

    code

    Activity activity = this;
    paymentClient.getPaymentMethods(activity, PAYMENT_METHODS_REQUEST_CODE);

    code

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    
        if (data == null) return;
    
        if (requestCode == PAYMENT_METHODS_REQUEST_CODE) {
            showPaymentMethodsResult(resultCode, data);
        }
    }
    
    private void showPaymentMethodsResult(int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            PaymentMethodsResponse response =
                (PaymentMethodsResponse) data.getSerializableExtra("response");
            // handle response
        } else {
            Exception exception =
                (Exception) data.getSerializableExtra("exception");
            // handle error
        }
    }

    6. Hosted Payment Page (HPP)

    API reference: POST /orders/hpp

    HPP delegates the checkout UI to the NPG-hosted payment page. The SDK supports three presentation strategies: return the HPP URL to the app, open the page inside a WebView, or open it through the platform in-app browser.

    ModeWho opens the pageMain advantageConsiderations
    URL onlyMerchant applicationMaximum control over navigationThe application must choose and manage the browser surface.
    Embedded WebViewSDK/application WebViewKeeps checkout visually inside the appWallets and browser capabilities may require extra WebView configuration.
    In-app browserChrome Custom Tabs / SFSafariViewControllerBrowser-grade behavior with an in-app transitionUI is less deeply embedded than a WebView.

    6.1 URL-only HPP

    This mode creates the HPP order and returns a CreateHostedOrderResponse containing the hosted page URL through getHostedPage() and a security token through getSecurityToken(). Despite the class name, Android v1.1.0 uses CreateHostedOrderWebViewRequest for this URL-only call. The application remains responsible for deciding how the returned hosted page is presented.

    iOS

    code

    do {
        let req: CreateHostedFieldOrderRequest // initialize the request
        let response = try await ngpclient!.CreateOrderHPP(param: req)
        // open/use the returned HPP URL
    } catch let e as ClientException {
        // handle client error
    } catch let e as UnauthorizedException {
        // handle authentication/authorization error
    } catch let e as ServerErrorException {
        // handle server error
    } catch {
        // handle unexpected error
    }

    Android

    code

    Activity activity = this;
    CreateHostedOrderWebViewRequest request; // initialize the request
    paymentClient.createHostedPaymentPage(
        activity,
        request,
        HPP_NO_WEBVIEW_REQUEST_CODE
    );

    code

    private void showHostedPaymentPageResult(int resultCode, Intent data) {
        CreateHostedOrderWebViewRequest request =
            (CreateHostedOrderWebViewRequest) data.getSerializableExtra("request");
    
        if (resultCode == RESULT_OK) {
            CreateHostedOrderResponse response =
                (CreateHostedOrderResponse) data.getSerializableExtra("response");
            // use the HPP URL returned in the response
        } else {
            Exception exception =
                (Exception) data.getSerializableExtra("exception");
            // handle error
        }
    }

    6.2 Embedded WebView HPP

    This mode displays the hosted payment page in an embedded WebView and returns the payment result through callbacks (iOS) or the activity-result contract (Android).

    iOS

    code

    do {
        let response = try await ngpclient!.CreateOrderHPPWebView(
            param: createMockedOrderRequestWebView(),
            cbResultOk: { operation in
                // handle successful payment result
            },
            cbResultCancel: { error in
                // handle cancellation
            },
            controller: self
        )
    } catch let e as ClientException {
        // handle client error
    } catch let e as UnauthorizedException {
        // handle authentication/authorization error
    } catch let e as ServerErrorException {
        // handle server error
    } catch {
        // handle unexpected error
    }

    Android

    code

    Activity activity = this;
    CreateHostedOrderWebViewRequest request; // initialize the request
    paymentClient.loadHostedPaymentPage(
        activity,
        request,
        HPP_WEBVIEW_REQUEST_CODE
    );

    code

    private void showHostedPaymentPageResult(int resultCode, Intent data) {
        CreateHostedOrderWebViewRequest request =
            (CreateHostedOrderWebViewRequest) data.getSerializableExtra("request");
    
        if (resultCode == RESULT_OK) {
            Operation response =
                (Operation) data.getSerializableExtra("response");
            // handle result
        } else {
            Exception exception =
                (Exception) data.getSerializableExtra("exception");
            // handle error
        }
    }

    Google Pay in Android WebView If the HPP offers Google Pay inside an Android WebView, the host app must enable Google Pay support for Android WebView. Google documents OR_BIBED_15 as a typical error when WebView support is not configured. Current requirements include compatible Google Play services / WebView versions, AndroidX WebKit support, manifest queries, and enabling the Payment Request API when supported. Always follow the latest Google Pay WebView documentation.

    6.3 In-app browser HPP

    This mode opens the hosted payment page using Chrome Custom Tabs on Android and SFSafariViewController on iOS. On Android v1.1.0 the public API requires a CreateHostedOrderRequest and a CustomTabsUI object; this differs from the incomplete sample in the original README.

    iOS

    code

    func createOrderHppSafariViewController() async throws {
        do {
            _ = try await npgsdk?.CreateOrderHPPSafariViewController(
                param: createMockedOrderRequestWebView(),
                cbResultOk: { operation in
                    // handle successful result
                },
                cbResultCancel: { _ in
                    // handle cancellation
                },
                controller: self
            )
        } catch let e as ClientException {
            // handle client error
        } catch {
            // handle unexpected error
        }
    }

    Android

    code

    Activity activity = this;
    CreateHostedOrderRequest request; // initialize the request
    
    CustomTabsUI customTabsUI = new CustomTabsUI(
        colorPrimaryLight,
        colorPrimaryDark,
        hideUrlBar,
        showTitle
    );
    
    paymentClient.loadCustomCustomTabs(
        activity,
        request,
        HPP_CUSTOMTAB_CODE,
        customTabsUI
    );

    Android Custom Tabs API - validated In ngpsdk-release.aar v1.1.0 the confirmed public signature is loadCustomCustomTabs(Activity, CreateHostedOrderRequest, int, CustomTabsUI). The unusual method name loadCustomCustomTabs is present in the released binary and is retained exactly.

    7. 2-Step payment

    Integration reference: 2-step payment

    The 2-Step flow uses the SDK card form to collect card data and starts the corresponding 2-step payment operation. The host application embeds the SDK-provided card UI and handles the returned payment result.

    iOS

    Add the SDK card form view to the storyboard, bind it to the view controller, then call the 2-step SDK method with a ThreeDSInitRequest.

    code

    @IBOutlet weak var cardData: Card2LinesForm!
    
    func twoStepsOrder() async throws {
        let req: ThreeDSInitRequest // initialize the request
    
        do {
            try await cardData.twoStepsOrder(
                sdk: ngpclient!,
                param: req,
                cbResultOk: { operation in
                    // handle successful response
                },
                cbResultCancel: { error in
                    // handle cancellation
                },
                controller: self
            )
        } catch let e as ClientException {
            // handle client error
        } catch let e as UnauthorizedException {
            // handle authentication/authorization error
        } catch let e as ServerErrorException {
            // handle server error
        } catch {
            // handle unexpected error
        }
    }

    Android

    Declare an SDK card-form view in the layout and call setup(this). Android v1.1.0 accepts the base CardForm type in both loadTwoStepPaymentPage(...) and loadThreeStepPaymentPage(...), so both CardFormInline and CardFormFull are structurally compatible with the public method signature. The sample below retains CardFormInline for the 2-Step UI.

    code

    <it.nexi.ngp.sdk.features.cardpayment.cardform.view.CardFormInline
        android:id="@+id/card_form"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
    <Button
        android:id="@+id/continue_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Continue"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/card_form" />

    code

    private CardFormInline cardForm;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.your_layout);
    
        cardForm = findViewById(R.id.card_form);
        cardForm.setup(this);
    
        ThreeDSOrderRequest orderRequest =
            (ThreeDSOrderRequest) getIntent().getSerializableExtra("request");
    
        Button continueBtn = findViewById(R.id.continue_btn);
        continueBtn.setOnClickListener(view ->
            paymentClient.loadTwoStepPaymentPage(
                this,
                cardForm,
                orderRequest,
                TWO_STEP_REQUEST_CODE
            )
        );
    }

    code

    private void showTwoStepPaymentResult(int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            ThreeDSPaymentResponse response =
                (ThreeDSPaymentResponse) data.getSerializableExtra("response");
            // handle response
        } else {
            Exception exception =
                (Exception) data.getSerializableExtra("exception");
            // handle error
        }
    }

    8. 3-Step payment

    Integration reference: 3-step payment

    The 3-Step flow follows the same integration pattern as the 2-Step flow but uses loadThreeStepPaymentPage(...). Android v1.1.0 accepts CardForm as the parameter type; the sample retains CardFormFull as a UI choice rather than presenting it as a mandatory 3-Step requirement.

    iOS

    code

    @IBOutlet weak var cardData: Card2LinesForm!
    
    func threeStepsOrder() async throws {
        let req: ThreeDSInitRequest // initialize the request
    
        do {
            try await cardData.threeStepsOrder(
                sdk: ngpclient!,
                param: req,
                cbResultOk: { operation in
                    // handle successful response
                },
                cbResultCancel: { error in
                    // handle cancellation
                },
                controller: self
            )
        } catch let e as ClientException {
            // handle client error
        } catch let e as UnauthorizedException {
            // handle authentication/authorization error
        } catch let e as ServerErrorException {
            // handle server error
        } catch {
            // handle unexpected error
        }
    }

    Android

    code

    <it.nexi.ngp.sdk.features.cardpayment.cardform.view.CardFormFull
        android:id="@+id/card_form"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    code

    private CardFormFull cardForm;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.your_layout);
    
        cardForm = findViewById(R.id.card_form);
        cardForm.setup(this);
    
        ThreeDSOrderRequest orderRequest =
            (ThreeDSOrderRequest) getIntent().getSerializableExtra("request");
    
        Button continueBtn = findViewById(R.id.continue_btn);
        continueBtn.setOnClickListener(view ->
            paymentClient.loadThreeStepPaymentPage(
                this,
                cardForm,
                orderRequest,
                THREE_STEP_REQUEST_CODE
            )
        );
    }

    code

    private void showThreeStepPaymentResult(int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            ThreeDSPaymentResponse response =
                (ThreeDSPaymentResponse) data.getSerializableExtra("response");
            // handle response
        } else {
            Exception exception =
                (Exception) data.getSerializableExtra("exception");
            // handle error
        }
    }

    9. MOTO

    Integration reference: MOTO

    Use the MOTO flow only for merchant configurations and use cases where Mail Order / Telephone Order is enabled and permitted by the NPG setup.

    iOS

    code

    do {
        let response = try await ngpclient!.moto(param: createMotoRequest())
        // handle response
    } catch let e as ClientException {
        // handle client error
    } catch let e as UnauthorizedException {
        // handle authentication/authorization error
    } catch let e as ServerErrorException {
        // handle server error
    } catch {
        // handle unexpected error
    }

    Android

    code

    Activity activity = this;
    MotoRequest request; // initialize the request
    paymentClient.processMoto(activity, request, MOTO_REQUEST_CODE);

    code

    private void showMotoResult(int resultCode, Intent data) {
        MotoRequest request =
            (MotoRequest) data.getSerializableExtra("request");
    
        if (resultCode == RESULT_OK) {
            MotoResponse response =
                (MotoResponse) data.getSerializableExtra("response");
            // handle response
        } else {
            Exception exception =
                (Exception) data.getSerializableExtra("exception");
            // handle error
        }
    }

    10. Wallets: Apple Pay and Google Pay

    The SDK provides native wallet integrations for Apple Pay on iOS and Google Pay on Android. These flows are separate from an HPP checkout that happens to offer the same wallet inside the hosted page.

    10.1 Apple Pay (iOS)

    Create the Apple Pay request, ask the SDK for the wallet button, and handle success, failure, and cancellation in the result callback.

    code

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let applePayRequest = createMockedApplePayRequest()
        let applePayButton = npgsdk!.applePay(on: self, param: applePayRequest) { result in
            switch result {
            case .success(let operation):
                print("Payment successful: \(operation)")
            case .failure(let error):
                print("Payment failed: \(error.localizedDescription)")
            case .cancelled:
                print("Payment cancelled by user")
            }
        }
    
        view.addSubview(applePayButton)
        applePayButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            applePayButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            applePayButton.bottomAnchor.constraint(
                equalTo: view.safeAreaLayoutGuide.bottomAnchor,
                constant: -20
            ),
            applePayButton.heightAnchor.constraint(equalToConstant: 50),
            applePayButton.widthAnchor.constraint(equalToConstant: 200)
        ])
    }

    10.2 Google Pay (Android)

    Add GooglePayFrameView to the activity layout, configure the Google Pay environment and button appearance, then provide both a GooglePayRequest and a GooglePayCallback. The button becomes enabled only after both values are set. The GooglePayRequestMock helper shown in the original README is not part of the released AAR and is therefore not used as a documented SDK API below.

    code

    <it.nexi.ngp.sdk.features.googlepay.GooglePayFrameView
        android:id="@+id/paymentFrame"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        app:layout_constraintTop_toBottomOf="@id/prev_btn"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:gpay_environment="TEST"
        app:gpay_buttonTheme="LIGHT"
        app:gpay_buttonType="CHECKOUT" />

    Supported view attributes in the supplied README:

    • gpay_environment - selects the Google Pay processing environment.

    • gpay_buttonTheme - selects the button theme (for example light or dark).

    • gpay_buttonType - selects the Google Pay button type.

    code

    GooglePayFrameView paymentFrame = findViewById(R.id.paymentFrame);
    
    GooglePayWalletConfig walletConfig = GooglePayWalletConfig.builder()
        .merchantName(merchantName)
        .merchantId(merchantId)
        .currencyCode(currencyCode)
        .countryCode(countryCode)
        .transactionId(transactionId)
        .totalPrice(totalPrice)
        .emailRequired(false)
        .billingAddressRequired(false)
        .shippingAddressRequired(false)
        .phoneNumberRequired(false)
        .build();
    
    GooglePayPaymentRequest paymentRequest = GooglePayPaymentRequest.builder()
        .order(order)
        .paymentSession(paymentSession)
        .build();
    
    GooglePayRequest request = GooglePayRequest.builder()
        .walletConfig(walletConfig)
        .paymentRequest(paymentRequest)
        .build();
    
    paymentFrame.setGooglePayRequest(request);
    paymentFrame.setPaymentCallback(new GooglePayCallback() {
        @Override
        public void onPaymentComplete(GooglePayResponse googlePayResponse) {
            // Handle successful payment result
        }
    
        @Override
        public void onPaymentFailure(Error error) {
            // Handle Google Pay / payment error
        }
    
        @Override
        public void onPaymentCancelled() {
            // Handle explicit user cancellation
        }
    });

    Production readiness The GooglePayRequestMock helper from the original README is not packaged in the released AAR. Build GooglePayWalletConfig, GooglePayPaymentRequest and GooglePayRequest using the SDK builders and populate them with values from the merchant/NPG configuration. Do not copy mock values into production.

    11. Error and cancellation handling

    Every payment integration should distinguish at least three outcomes: successful SDK/payment result, user cancellation, and technical/business error. Avoid treating a cancellation as a generic failure because the user experience and retry strategy are different.

    OutcomeRecommended handlingNote
    SuccessProcess the SDK response and continue with the merchant confirmation flow.Do not expose sensitive response data in logs.
    User cancellationReturn the customer to a safe checkout state and allow an intentional retry.Do not display a technical error if the user simply cancelled.
    ClientExceptionInspect the SDK-provided error details and request content.Typically integration/request-side.
    UnauthorizedExceptionCheck credentials, environment, merchant enablement, and authorization.Do not retry indefinitely.
    ServerErrorExceptionTreat as a remote/service error and apply the merchant retry/error strategy.Preserve correlation information where available.
    Unexpected exceptionFail safely and capture diagnostic data without sensitive payloads.Keep customer messaging generic and actionable.

    12. Security and mobile implementation guidance

    • Use only supported SDK and platform versions and keep dependencies updated according to the NPG release policy.

    • Never log PAN, CVV/CVC, wallet tokens, authentication payloads, API credentials, or full payment responses unless explicitly sanitized.

    • Prefer SDK-provided card-entry views rather than copying card data into merchant-owned UI components unless the integration specification explicitly requires otherwise.

    • Keep test and production configuration separate and make environment selection non-ambiguous in release builds.

    • Handle app process death, backgrounding, and interrupted authentication without assuming the final transaction state.

    • For hosted flows, validate redirect/callback handling and prevent untrusted URLs from being opened in privileged WebViews.

    • For Google Pay inside Android WebView, follow the current Google WebView integration requirements and test on supported WebView/Google Play services versions.

    • Validate the final payment state using the authoritative NPG flow defined for the integration; UI completion alone is not a substitute for payment-state verification.

    Android WebView compatibility Google currently documents Android WebView requirements for Google Pay and specifically associates OR_BIBED_15 with missing/incorrect WebView enablement. The external platform requirements can change independently of the NPG SDK, so keep this part of the merchant checklist versioned.

    13. FAQ

    Which HPP mode should I use?

    Use URL-only when the application wants full control over navigation, embedded WebView when the checkout must stay visually inside the app, and the in-app browser option when browser behavior is preferred while keeping the user in an app-like transition.

    Is native Google Pay the same as Google Pay shown inside HPP?

    No. Native Google Pay uses GooglePayFrameView and the SDK callback. In an HPP flow, the wallet is rendered by the hosted web checkout. If that hosted checkout runs inside Android WebView, the WebView must support Google Pay.

    What does OR_BIBED_15 mean on Android?

    Google documents OR_BIBED_15 as an error that can occur when Google Pay is used from a WebView that is not correctly enabled for Google Pay. Check the current Google Pay Android WebView guide and the application/WebView requirements.

    Why do Android examples use request codes and onActivityResult?

    Android SDK v1.1.0 calls startActivityForResult(...) internally from PaymentClient, therefore the documented integration contract returns results through onActivityResult(...). A migration to the modern AndroidX Activity Result API would require an SDK-level API change or a different public contract; do not silently replace the documented callback pattern while using this SDK release.

    Can I assume RESULT_OK means the order is definitively settled?

    Treat RESULT_OK as the SDK flow result and follow the NPG integration specification for the authoritative transaction/payment state. Do not infer financial settlement solely from a UI callback.

    Can I use production keys in source code?

    Do not hard-code production credentials. Follow the NPG credential model for mobile clients and your organization's secure configuration rules.

    Why are CardFormInline and CardFormFull different?

    They provide different SDK-owned card-entry layouts. In Android v1.1.0, both 2-Step and 3-Step public methods accept the common CardForm base class, so CardFormInline is not technically restricted to 2-Step and CardFormFull is not technically restricted to 3-Step. Choose the view according to the desired UX and validated merchant requirements.

    What should be tested before go-live?

    At minimum: success, decline/error, user cancellation, authentication challenges, app background/restore, network interruption, repeated taps, test-to-production configuration, every enabled payment method, and WebView wallet behavior if HPP is embedded.

    Was this helpful?

    What was your feeling about it?