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.
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
Description | Package | Language/Framework |
---|---|---|
Stitch SDK | @stitch-money/node | JavaScript |
Stitch SDK | stitch-money-api | Python |
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.
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.
Stitch only supports device tokens authenticated with a 3D Secure cryptogram (CRYPTOGRAM_3DS
).
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 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 thePaymentsClient
instance loadPaymentData
returns aTask
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
- Python
- JavaScript
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.
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.
- Apple Pay
- Samsung Pay
- Google Pay
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
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_samsung_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.SAMSUNG_PAY,
payment_token,
quantity,
currency,
nonce,
reference
)
return transaction
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_google_pay_request(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.GOOGLE_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.
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.
Installation
Run the following command to install the npm package.
npm install @stitch-money/node
Import and initialise the SDK with the required arguments. The secret
argument must be set with your Stitch client secret.
import { init, type StitchTransaction } from "@stitch-money/node";
const walletPayClient = init(clientId, WALLET_MERCHANT_IDENTIFIER, secret);
API Endpoint Handlers
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.
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.
- Apple Pay
- Samsung Pay
- Google Pay
export async function POST(request: Request) {
const { paymentToken } = req.body;
const nonce = generateNonce();
const quantity = 1;
const currency = "ZAR";
const reference = "REF";
const transaction = await walletPayClient.create(
"APPLE_PAY",
paymentToken,
quantity,
currency,
nonce,
reference
);
return transaction;
}
export async function POST(request: Request) {
const { paymentToken } = req.body;
const nonce = generateNonce();
const quantity = 1;
const currency = "ZAR"
const reference = "REF";
const transaction = await walletPayClient.create(
"SAMSUNG_PAY",
paymentToken
quantity,
currency,
nonce,
reference
);
return transaction;
}
export async function POST(request: Request) {
const { paymentToken } = req.body;
const nonce = generateNonce();
const quantity = 1;
const currency = "ZAR";
const reference = "REF";
const transaction = await walletPayClient.create(
"GOOGLE_PAY",
paymentToken,
quantity,
currency,
nonce,
reference
);
return transaction;
}
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 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
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, 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:
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. |
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:
- Apple Pay
- Samsung Pay
- Google Pay
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.
- 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 | authorizationFailure |
Other | SUCCESS | - |