Skip to main content

Mobile Application Integration Process

To accept wallet payments in a native application, you need to integrate with the applicable wallet provider(s) and Stitch, in addition to the aforementioned configuration requirements.

Stitch distributes JavaScript and Python packages that encapsulate the server-side Stitch API integration. These packages can be used to create wallet payments for Apple Pay, Samsung Pay, and Google Pay™. Stitch also supports a direct integration should you elect to extend an existing Stitch integration.

tip

Using the Stitch SDK applicable to your platform is recommended for first-time Stitch clients that do not have a pre-existing integration to reduce development time. For existing clients onboarding with Wallets, extending your existing Stitch API integration is the quickest approach to accept digital wallet payments.

Server

DescriptionPackageLanguage/Framework
Stitch SDK@stitch-money/nodeJavaScript
Stitch SDKstitch-money-apiPython
Coming Soon

iOS and Android SDKs are in development to streamline the provider integration for merchants that do not require fine-grained control or extensive customization of the on-device payment experience.

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.

Authentication Mode

Stitch only supports device tokens authenticated with a 3D Secure cryptogram (CRYPTOGRAM_3DS).

System Requirements

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

  1. Distributed through the Google Play store.
  2. Built using the following configuration:
  3. A minSdkVersion of 21 or higher
  4. 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 summary of the process required to integrate and configure Google Pay in an Android application. View the Google Pay for Payments documentation for guides and resources.

Configure Payment Client

  • Configure your Google Pay API version
  • Request a payment token for Stitch using the supplied gateway merchant ID
{
"gateway": "stitch"
"gatewayMerchantId": "STITCH_GATEWAY_MERCHANT_ID"
}
  • Allow only authenticated device tokens
private val allowedCardAuthMethods = JSONArray(listOf("CRYPTOGRAM_3DS"))
  • Create a PaymentsClient instance to interact with the Google Pay API

Add Payment Button

  • Call isReadyToPay() to determine if the user can make payments with the Google Pay API
  • Add a PayButton layout to the application

Create Payment Request

  • Create a PaymentDataRequest JSON object to create the payment sheet
  • Use blocks to add merchant and transaction information

Display Payment Sheet

  • Call the loadPaymentData request on the PaymentsClient instance
  • loadPaymentData returns a Task object with the operation result

Handle Payment Response

  • Extract the payment token from the PaymentData result object
  • Submit the payment token to your server to process the wallet payment
  • Report the success or failure of the transaction

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 using the Stitch SDK (Python and JavaScript) or directly via the Stitch API.

Stitch SDK

Installation

Run the following command to install the Python package.

pip3 install stitch-money-api

Import and initialise a Wallet class instance

from stitch.payins import Wallets
from dotenv import load_dotenv

load_dotenv()

client_id = os.getenv("STITCH_CLIENT_ID")
client_secret = os.getenv("STITCH_CLIENT_SECRET")

stitch_sdk = Wallets(client_id, client_secret, 'merchant.money.stitch')

API Endpoint Handler

The create function must be invoked on your application server or backend-for-frontend. The payment token contains the payment encryption and transaction data that must be transmitted to Stitch.

Key Points

API routes (handlers) for each wallet provider are functionally identical. Ensure that the correct wallet type is specified as an argument to the create function.

The sample code example demonstates the usage of the SDK in a Pyramid framework request handler. Map the endpoint to the desired URL pattern in the Pyramid routes definition.

from pyramid.view import view_config
from pyramid.response import Response
from stitch.utils.types import Wallet, Currency
import json
import uuid

@view_config(route_name='create', request_method='POST', renderer='json')
def create_apple_pay_payment(request):
data = request.json_body
payment_token = data.get('payment_token')

nonce = str(uuid.uuidv4())
quantity = 1
currency = Currency.ZAR
reference = "StitchTest"

transaction = sdk.create(
Wallet.APPLE_PAY,
payment_token,
quantity,
currency,
nonce,
reference
)

return transaction

The response is a stitch.utils.types.Transaction that contains a status field that can be consumed and transmitted to the Android application.

Note

The status field contained in the response is a synchronous update on the status of a payment. Note that this status will also be returned once subscribed to updates via webhook.

The response is a StitchTransaction that contains a status field that can be consumed and transmitted to the Android application.

Direct 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, they will be redirected back to your specified redirect_uri, together with the transactionId as a query parameter.

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.

Status by ID

You can check any transaction's status, as well as other corresponding details, with a query to the GraphQL API. An example query is shown below:

Webhook Subscriptions

Wallet payments require that you subscribe to transaction webhooks to receive asynchronous updates on payment statuses, since a Sticth wallet payment has no associated payment request.

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

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

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 payment request status is changed from the TransactionSuccess state. This means that you will receive webhooks for each of the following transaction statuses:

  • TransactionSuccess
  • TransactionFailure

Querying Transactions

You may want to query the Stitch API for a transaction at any point.

Transaction by ID

We recommend using the Stitch-supplied id to do this, as it is most performant, but you may use any of the identifying fields (including externalReference and nonce) associated with the Transaction to do the same.

Transaction by Reference

The example below shows the query for all transactions that match the externalReference supplied.

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.04FAILUREauthorizationFailure
OtherSUCCESS-