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.
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.
- Open your project with Xcode. In the Project navigator, select the project.
- Choose the target for the app from either the Project/Targets pop-up menu or in the Targets section of the outline view.
- Click the Signing & Capabilities tab in the project editor.
- In the toolbar, click the Library button (+) to open the Capabilities library and select the Apple Pay capability.
- Within the Apple Pay capability, click the refresh button to synchronize your merchant identifiers from the Apple Developer site.
- 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 afingerprint
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 thepresent
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 aNSError
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.
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.
Stitch only supports a Network (Direct) Token mode for processing. The encrypted payment token is passed to Stitch directly for decryption and processing.
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.
- Add
samsungpay.jar
dependency for the SDK to your module's Gradle build file. - Add a spay_sdk_api_level
meta-data
element to the<application>
element of your project'sAndroidManifest.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.
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.
- Add the Google Play services dependency for the Google Pay API to your module's Gradle build file (typically
app/build.gradle
orapp/build.gradle.kts
). - Add a Google Pay API
meta-data
element to the<application>
element of your project'sAndroidManifest.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
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"))
- 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").
- 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 thedeviceInformation
object are required, including all ofdeviceId
,ip
andscreenDimensions
.
- Apple Pay
- Samsung Pay
- Google Pay
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:
- Apple Pay
- Samsung Pay
- Google Pay
The requireSecure3d
parameter should only be specified if your client is configured to allow you to control performing 3DS on payments. Including this parameter without proper configuration will result in an invalid configuration error. Please reach out to Stitch if you would like to enable this feature.
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
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.
Parameter | Description |
---|---|
transactionId | The payment's Stitch ID |
flow | The 3DS interaction type i.e. challenge or frictionless |
externalReference | The payment's external reference |
status | The payment's final status i.e. TransactionSuccess or TransactionFailure |
statusReason | The 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:
Status | Description |
---|---|
TransactionPending | A 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. |
TransactionFailure | A payment authorised by a user but unsuccessful and the requested funds were not captured. |
TransactionSuccess | A 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:
Reason | Description |
---|---|
authorizationFailed | The transaction was declined or blocked. |
authorizationNotFinalised | The transaction could not be processed by the acquirer. |
blockedByFraudChecks | The transaction was blocked due to fraud checks. |
downstreamProviderError | The transaction could not be processed due to downstream error. |
exceedsCardWithdrawalLimit | The transaction was declined due to withdrawal limits exceeded. |
insufficientFunds | The transaction was declined due to insufficient funds. |
internalServerError | The transaction could not be processed due to a server error. |
invalidCardError | The transaction was declined due to an expired card. |
invalidConfigurationError | The client has invalid or missing configuration. |
invalidTransactionError | The authorised payment amount (for the payment token) does not match the transaction input amount. |
secure3dDeclined | The user has declined 3DS authentication. |
secure3dLookupFailed | 3DS authentication attempt could not be initiated. |
secure3dNotCompleted | The user has not completed 3DS authentication. |
tokenDecryptionError | The 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:
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.
- 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 Pay
- Google Pay
- Samsung Pay
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.
Using a Stitch Test client for Google Pay does not require adding a card to the device used to initiate payment. You will need to add the Google Account on the device to the following Google Group. Clicking the Google Pay button will then display a suite of test cards to choose from for completing a test payment.
Samsung Pay requires a card from your acquirer. Please contact support@stitch.money for more information on this.
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:
Amount | Status | Reason |
---|---|---|
1.01 | FAILURE | insufficientFunds |
4.04 | FAILURE | authorizationFailed |
Other | SUCCESS | - |