Skip to main content

Mobile Application Integration Process

To accept wallet payments in a native application, you will need to integrate with the applicable wallet provider(s) on the client-side, together with Stitch on the server-side, via API. Aforementioned configuration must also be completed and the payment methods must be enabled on your Stitch client.

iOS App

This sequence diagram outlines the high-level native and backend component interactions for Apple Pay.

sequenceDiagram autonumber participant U as User participant A as iOS App participant PK as Passkit Apple Pay Framework (PK) participant BFF as Backend for Frontend participant PSDK as Stitch SDK U->>A: initiate checkout flow rect rgb(239, 232, 252) note right of A: Device Interaction A->>PK: render payment button if [canMakePayments, canSetupCards] A->>PSDK: call getDeviceData(...) for fingerprint response PSDK->>A: return device fingerprint response U->>A: tap Pay with Apple Pay button A->>PK: create PKPaymentRequest() PK->>A: display payment sheet (PKPaymentAuthorizationController()) U->>PK: authorize payment with biometrics PK->>A: call didAuthorizePayment(token, ...) end rect rgb(239, 232, 252) note right of A: Server-side Processing A->>BFF: submit PKPaymentToken and fingerprint response BFF->>PSDK: call create(...) PSDK->>BFF: return ApplePayTransaction BFF->>A: return ApplePayTransaction.status end rect rgb(239, 232, 252) note right of A: Device Interaction A->>PK: call completion(...) with PKPaymentAuthorizationResult status PK->>A: dismiss payment sheet A->>U: redirect to success screen end

Setup

To accept Apple Pay payments in your iOS application, you need to enable Apple Pay in Xcode in addition to creating a merchant ID and payment processing certificate. Complete the following steps to enable the Apple Pay capability in your Xcode project.

  1. Open your project with Xcode. In the Project navigator, select the project.
  2. Choose the target for the app from either the Project/Targets pop-up menu or in the Targets section of the outline view.
  3. Click the Signing & Capabilities tab in the project editor.
  4. In the toolbar, click the Library button (+) to open the Capabilities library and select the Apple Pay capability.
  5. Within the Apple Pay capability, click the refresh button to synchronize your merchant identifiers from the Apple Developer site.
  6. Select the merchant identifier to use with this app.

Integration

Integrating Apple Pay into your iOS application requires the following:

  • For fingerprinting information to be associated to transactions, the Stitch iOS SDK should be used. Contact Stitch for access to this SDK during your integration journey.
  • For the Apple Pay button to be rendered, and tokens to be returned for processing wallet transactions, use Apple Pay PassKit.

At a high-level, the following steps should be performed on your client-side integration:

1. Device Payment Ability and Button

  • Check for the device's ability to make payments using the PKPaymentAuthorizationController.canMakePayments method.
  • Render a pre-built Apple Pay payment button with an instance of PKPaymentButton.
  • On successful render of the button, call client.getDeviceData using the Stitch SDK to get a fingerprint response:
let client = StitchFingerprintClient.getInstance(clientId: "your-stitch-client-id")

Task {
do {
let fingerprint = try await client.getDeviceData(userId: "your-user-identifier") // Optional user identifier, to facilitate support queries
} catch {
// Handle error
}
}

2. Payment Request and Sheet

  • Call PKPaymentRequest to configure a request for payment, that is created when the user taps the Apple Pay button. This should include:
    • Your configured merchant identifier,
    • Supported payment networks,
    • Currency and country codes, and
    • Payment summary items.
  • Use a PKPaymentSummaryItem to display the individual charge(s) description to the user, on the payment sheet.
  • Call the PKPaymentAuthorizationController with the above-created payment request, and display the sheet with the present method.

3. Payment Processing

  • In the paymentAuthorizationController method implementation, submit the token and fingerprint to your server side (for processing the wallet payment via Stitch). This will be called when a user authorises payment.
  • The returned status from your server-side should be mapped to the corresponding PKPaymentAuthorizationResult. If there is a failure, include a NSError with appropriate description that would be shown to the user in the sheet.
  • Provide the status and errors to the completion handler, that will display on the sheet accordingly.
func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {

var errors = [NSError]()
var status = PKPaymentAuthorizationStatus.success

// Send the payment token, and device fingerprint, to server-side request for processing transaction with Stitch.
// Consume transaction result, and set any appropriate errors if status is failure.
// Return status/errors in completion handler, for Apple Pay sheet.

completion(PKPaymentAuthorizationResult(status: status, errors: errors))
}

4. Payment Sheet Dismissal

  • Although optional, it is highly recommended to implement the paymentAuthorizationControllerDidFinish method so the application can register when the payment sheet has been dismissed.
  • Within controller.dismiss, navigate the user back to your app's next screen, such as a summary of the user's order.
func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
// Ensure the payment sheet is dismissed
controller.dismiss {
// Navigate to payment/order summary
}
}

Android App

Android applications can support Samsung Pay and Google Pay payments. The component interactions are analogous to Apple Pay in an iOS application: display a payment sheet, authenticate the user, submit the payment token for processing, and handle the payment response.

sequenceDiagram autonumber participant U as User participant A as Android App participant PK as Samsung Pay SDK/Google Pay API participant BFF as Backend for Frontend participant SDK as Stitch SDK U->>A: initiate checkout flow rect rgb(239, 232, 252) note right of A: Device Interaction A->>PK: add payment button U->>A: tap payment button A->>PK: create payment request PK->>A: display payment sheet U->>PK: authorize payment PK->>A: handle authorization end rect rgb(239, 232, 252) note right of A: Server-side Processing A->>BFF: submit payment token BFF->>SDK: create(...) SDK->>BFF: Transaction BFF->>A: Transaction.status end A->>U: report status

Samsung Pay

Setup

To accept Samsung Pay payments on supported Samsung Galaxy devices, create a service and register the application in the Samsung Pay Developers portal.

Token Mode

Stitch only supports a Network (Direct) Token mode for processing. The encrypted payment token is passed to Stitch directly for decryption and processing.

System Requirements

The Samsung Pay SDK is designed exclusively for Samsung mobile devices supporting Samsung Pay and running Android Lollipop 5.1 (Android API level 22) or later versions of the Android OS. The SDK’s In-App Payments functionality requires Android 6.0 (M) (Android API level 23) or later versions of the Android OS.

Complete the following steps to configure your application.

  1. Add samsungpay.jar dependency for the SDK to your module's Gradle build file.
  2. Add a spay_sdk_api_level meta-data element to the <application> element of your project's AndroidManifest.xml file to configure the API.

Integration

Below is a high-level summary of the process required to integrate Samsung Pay into an Android-based partner application on Samsung devices. View the SDK documentation for more detailed guidance on offering Samsung Pay.

Add Payment Button

  • Determine if payments are supported with the on-device provisioned card
  • Render a pre-built Samsung Pay payment button

Create Payment Request

  • Create a transaction request using the custom payment sheet (CustomSheetPaymentInfo class)
  • Populate the payment sheet with merchant and transaction information

Display Payment Sheet

  • Call startInAppPayWithCustomSheet() to initiate the payment request with the custom payment sheet.
  • The updateSheet method updates the payment sheet if any values on the sheet are changed.

Handle Payment Response

  • The onSuccess callback (CustomSheetTransactionInfoListener method) is invoked on payment authorisation
  • Submit the entire payment token (paymentCredential) to your server to process the wallet payment
  • Report the success or failure of the transaction

Google Pay

Setup

To accept Google Pay payments on Android devices, you need to register with the Google Pay and Wallet Console.

System Requirements

To use the Google Pay API on Android, your app must be:

  • Distributed through the Google Play store.
  • Built using the following configuration:
    • A minSdkVersion of 21 or higher.
    • A compileSdkVersion of 34 or higher. :::

Complete the following steps to configure your application.

  1. Add the Google Play services dependency for the Google Pay API to your module's Gradle build file (typically app/build.gradle or app/build.gradle.kts).
  2. Add a Google Pay API meta-data element to the <application> element of your project's AndroidManifest.xml file to configure the API.

Integration

Below is a high-level overview of the steps to integrate and configure Google Pay in an Android application, tailored specifically to processing payments via Stitch. For detailed step-by-step guidance, refer to the Google Pay for Payments documentation.

Step 1: Configure Payment Client

  • Configure your Google Pay API version
  • Request a payment token for Stitch using the supplied gateway merchant ID
Note

The gatewayMerchantId is a unique identifier that will be provided by Stitch and must be correctly configured for secure payment processing. Replace STITCH_GATEWAY_MERCHANT_ID with the value supplied by Stitch to avoid tokenization failures.

{
"gateway": "stitch"
"gatewayMerchantId": "STITCH_GATEWAY_MERCHANT_ID"
}

Step 2: Specify allowed card authentication modes

Available Google Pay payment methods include cards from a user's Google account (PAN_ONLY) and device tokens authenticated with a 3D Secure cryptogram (CRYPTOGRAM_3DS) on Android devices. To ensure both card authentication methods are presented to users, configure the allowedCardAuthMethods parameter in your API request as follows:

private val allowedCardAuthMethods = JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS"))

Step 3: Specify allowed card networks

Stitch currently supports Mastercard and Visa cards for Google Pay transactions. To ensure only supported card networks are presented to users, configure the allowedCardNetworks parameter in your API request as follows:

private val allowedCardNetworks = JSONArray(listOf("MASTERCARD", "VISA"))
Supported Card Networks
  • Stitch currently exclusively supports Mastercard and Visa cards for processing Google Pay payments. Specifying unsupported card networks in your configuration will result in an error. Ensure that only these networks are included to avoid issues during transaction processing.

Step 4: Create a PaymentsClient instance to interact with the Google Pay API

fun createPaymentsClient(context: Context): PaymentsClient {
val walletOptions = Wallet.WalletOptions.Builder()
.setEnvironment(Constants.PAYMENTS_ENVIRONMENT)
.build()

return Wallet.getPaymentsClient(context, walletOptions)
}

Step 5: Display the Google Pay button

Before you display the Google Pay button, call the isReadyToPay() API to determine if the user can make payments with the Google Pay API. Once you have determined that the user can make payments, add a PayButton layout to the application as described here.

Step 6: Create a PaymentDataRequest

The PaymentDataRequest JSON object defines the merchant and transaction details displayed to the user on the Google Pay payment sheet. Since this affects what the user sees just before confirming payment, ensure the information is clear, accurate, and user-friendly. For a complete list of configuration options, refer to the TransactionInfo JSON object documentation.

Recommended Elements

  • merchantName: A name identifying your business.
  • totalPrice: Total transaction value, optionally including up to two decimals (e.g. "10.00").
  • transactionId: Unique ID for the payment attempt (useful for troubleshooting).
  • currencyCode: ISO 4217 currency code (matching the currency of the transaction e.g. "ZAR").
Note
  • Stitch currently does not support collection or verification of address details for wallets.
  • Some fields are required by regulation. Ensure all mandatory fields are included for compliance with regional and industry standards.

Step 7: Initiate the payment process with Google Pay

To begin the payment process, use the loadPaymentData request with the PaymentsClient object. This triggers the Google Pay payment selector and returns a Task object containing the result.

Key Steps:

  • Call the loadPaymentData method with the PaymentDataRequest object created in the previous step.
  • Extract the payment token from the Task result object and use it to create the payment transaction to your server.

Server-side Integration

The integration with the Stitch API should run on your trusted application server as calls are authenticated using your sensitive Stitch credentials. This guide describe integrating directly via the Stitch API.

The create SDK function encapsulates the Stitch API initiateTransaction call. To create a wallet payment, a Stitch API initiateTransaction mutation call is required in order to initiate the payment. Note that a Stitch client token with the scope transaction_initiate is required to initiate any wallet transactions via the API.

The mutation must be called in server-side payment creation handlers using the payment token and fingerprint transmitted from the native application.

The input variable object must be constructed distinctly for each wallet provider. See the example Variables object for each mutation below. Note the fields that should be passed from your client-side to your server-side for processing:

  • The payment token from the client-side must be base64-encoded, before being specified in the token input field. This applies for all wallet providers.
  • The fingerprint response should be specified in the deviceInformation.fingerprint field. If this is unable to be provided, other fields within the deviceInformation object are required, including all of deviceId, ip and screenDimensions.
note

Unlike the integration for Samsung Pay on Web, a referenceId is not passed from the client-side. Rather, the token passed from the client is handled identically to Apple Pay and Google Pay, passed as a base64-encoded value in the token field.

Enforcing 3DS

The default configuration for Wallet transactions is for 3DS to not be enforced across transactions. However, if it is required to enforce 3DS on a per-transaction basis, this is done by specifying the requireSecure3d boolean as true within the respective payment method input, for example applePay.requireSecure3d. These are shown in the Variables of the example requests, below:

Handling Transaction Responses

Default Transactions

In the default setup, with 3DS not enforced on a transaction, the state field contained in the response is a synchronous update on the status of a payment. This will either be TransactionSuccess or TransactionFailure (with a corresponding reason). Note that this status will also be returned as a webhook update, when subscribed to transaction webhooks.

3DS-Enforced Transactions

Should 3DS have been enforced on a transaction (whether dynamically, based on agreed-upon configuration with Stitch, or per-transaction as described above), a transaction initiation response will return a TransactionPending status, as well as an interactionUrl.

The user must visit this URL, after appending a redirect_uri query parameter. This will guide the user through the required 3DS interaction to complete their transaction.

As an example, if you choose to redirect your user to the whitelisted URL https://example.com/payment, you'd append the following additional query string to the url returned from the API: ?redirect_uri=https%3A%2F%2Fexample.com%2Fpayment. The full URL you would expose to the user should look similar to the following:

https://3ds.stitch.money/02fa5c7f-3aea-4545-b4e9-5af7e128ff47?redirect_uri=https%3A%2F%2Fexample.payment
danger

The URL specified as the redirect_uri must be secure i.e. an HTTPS URL.

Once the user has successfully completed the interaction and the payment has been processed, they will be redirected back to your specified redirect_uri with the following query parameters.

ParameterDescription
transactionIdThe payment's Stitch ID
flowThe 3DS interaction type i.e. challenge or frictionless
externalReferenceThe payment's external reference
statusThe payment's final status i.e. TransactionSuccess or TransactionFailure
statusReasonThe optional reason for the payment's status

You will also receive a corresponding transaction webhook to confirm the status of the transaction.

Transaction Statuses

The table below describes the different statuses of a wallet payment:

StatusDescription
TransactionPendingA payment is initialised and awaiting user authentication. If an interactionUrl is returned, the user should be directed to this for the transaction to proceed. This is currently only applicable when handling 3DS-enforced transactions.
TransactionFailureA payment authorised by a user but unsuccessful and the requested funds were not captured.
TransactionSuccessA payment has been successfully made and the requested funds were captured.

Failure Reasons

The TransactionFailure status indicates that the wallet transaction failed to be initiated, and includes a reason explaining the cause. Potential failure reasons are detailed below:

ReasonDescription
authorizationFailedThe transaction was declined or blocked.
authorizationNotFinalisedThe transaction could not be processed by the acquirer.
blockedByFraudChecksThe transaction was blocked due to fraud checks.
downstreamProviderErrorThe transaction could not be processed due to downstream error.
exceedsCardWithdrawalLimitThe transaction was declined due to withdrawal limits exceeded.
insufficientFundsThe transaction was declined due to insufficient funds.
internalServerErrorThe transaction could not be processed due to a server error.
invalidCardErrorThe transaction was declined due to an expired card.
invalidConfigurationErrorThe client has invalid or missing configuration.
invalidTransactionErrorThe authorised payment amount (for the payment token) does not match the transaction input amount.
secure3dDeclinedThe user has declined 3DS authentication.
secure3dLookupFailed3DS authentication attempt could not be initiated.
secure3dNotCompletedThe user has not completed 3DS authentication.
tokenDecryptionErrorThe payment token could not be decrypted.

Querying Transactions

Transaction by ID

For implementing redundancy checks and logic, it is possible to query transaction statuses and details over the Stitch GraphQL API. Note that querying with the Stitch-provided id is the most performant, and the recommended approach.

Transaction by External Reference

Alternatively, querying by an externalReference is possible, and may be done with a filtering query, as follows:

note

When including this filter, the specific type of wallet transaction is required together with the external reference. As an example, the ApplePayTransaction query is shown above for Apple Pay transactions.

Webhook Subscriptions

Wallet payments require that you subscribe to transaction webhooks to receive asynchronous updates on transaction status changes.

If the subscription is successfully created, the body returned by the request will look similar to the sample in the Example Response tab in the widget above.

The webhook will contain important information regarding the transaction, including the selected wallet provider, the transaction retrieval reference number (RRN) (used for reconcilliation), external reference, and nonce.

For more information on receiving webhook events, listing active webhook subscriptions, unsubscribing from webhooks and validating signed webhook subscriptions, please visit the Webhooks page.

Webhook Statuses

When subscribed to the transaction webhook filter type, webhook updates will be sent whenever a refund transaction is updated to either of the following statuses:

  • TransactionSuccess
  • TransactionFailure

Testing Payment Initiation

To test payment initiation, you may use any device supported by the wallet providers applicable to your selected integration. See the Google Pay integration checklist for a more detailed description of recommended testing. Note that not all test cases/paths are applicable to the gateway integration.

Note
  • Payment initiation testing only applies to Stitch test clients.
  • A real and valid credit/debit card must be added to either the Apple, Samsung and/or Google Wallet application.
  • No funds will be captured when completing a payment with a real card and a transaction initiated by a test client.

Test Device Tokens

To simulate transaction initiation requests on test clients, you can specify J2V4YW1wbGVQYXltZW50TWV0aG9kVG9rZW4n as the paymentToken to bypass token decryption and validation that would normally be performed on a real token.

Test Cards

Testing the integration on a real device may require linking a test card to that device. For each wallet method this approach is distinct.

Apple provides a number of test cards that can be added to an Apple Wallet. These require registering a sandbox account and signing into a test device with that account. See Apple's Developer Sandbox Testing page for more details.

Simulating Transaction Statuses

For testing purposes, specific amounts can be used to simulate different scenarios when using a test client. The table below shows the mapping between amounts and transaction statuses:

AmountStatusReason
1.01FAILUREinsufficientFunds
4.04FAILUREauthorizationFailed
OtherSUCCESS-