Skip to main content

Web Application Integration Process

This integration guide pertains to applications built using web-based frameworks. Stitch provides a JavaScript client-side SDK for accepting wallet payments. Stitch also vends framework-agnostic Web and React components to support quickly adding wallet payment buttons to your interface. The component supports customisation within the brand guidelines stipulated by Apple Pay, Samsung Pay and Google Pay™.

Stitch also maintains JavaScript and Python server-side packages that encapsulates the integration with the Stitch API. Note that use of this SDK is not required and you can integrate directly with the Stitch API to create wallet payments. To offer all supported wallet providers, the aforementioned configuration must be completed and the payment methods must be enabled on your Stitch client.

Client

DescriptionPackageLanguage/Framework
Stitch SDK@stitch-money/clientJavaScript
React Components@stitch-money/reactReactJS
Web Components@stitch-money/webWeb/Angular

Server

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

Component Interactions

This sequence diagram outlines the high-level client and server-side component interactions for Apple Pay, Samsung Pay and Google Pay. The component interactions are generalised across providers, but note that the flows differ subtly. For example, there is no merchant verification step required for Google Pay.

sequenceDiagram autonumber participant U as User participant MFE as Merchant Client (FE) participant CSDK as Stitch SDK (FE) participant RSDK as React SDK (FE) participant MBE as Merchant Server (BE) participant S as Stitch API (/graphql) MFE->>CSDK: supportedPaymentMethods() CSDK-->>MFE: WalletType[] par Apple Pay MFE->>CSDK: onClickApplePaySessionHandler() CSDK->>MFE: onClick Event Handler and Samsung Pay MFE->>CSDK: onClickSamsungPaySessionHandler() CSDK->>MFE: onClick Event Handler and Google Pay MFE->>CSDK: onClickGooglePaySessionHandler() CSDK->>MFE: onClick Event Handler end MFE->>RSDK: Import PayWithWalletButton activate RSDK RSDK->>MFE: PayWithWalletButton Component deactivate RSDK alt Apple Pay Supported MFE->>U: Render Payment Button U-->>MFE: Tap "Pay with Apple Pay" Button MFE-->>CSDK: button.onClick() CSDK-->>MBE: POST /api/apple-pay/verify activate MBE MBE-->>S: POST validateApplePayMerchant activate S S-->>MBE: sessionData deactivate S MBE-->>CSDK: sessionData deactivate MBE CSDK->>U: Display Payment Sheet U-->>CSDK: Authorize Payment CSDK-->>MBE: POST /api/apple-pay/create activate MBE MBE-->>S: POST initiateTransaction activate S S-->>MBE: ApplePayTransaction deactivate S MBE-->>CSDK: ApplePayTransaction deactivate MBE CSDK->>U: Payment Status end alt Samsung Pay Supported MFE->>U: Render Payment Button U-->>MFE: Tap "Pay with Samsung Wallet" Button MFE-->>CSDK: button.onClick() CSDK-->>MBE: POST /api/samsung-pay/verify activate MBE MBE-->>S: POST verifySamsungPay activate S S-->>MBE: sessionData deactivate S MBE-->>CSDK: sessionData deactivate MBE CSDK->>U: Display Payment Sheet U-->>CSDK: Authorize Payment CSDK-->>MBE: POST /api/samsung-pay/create activate MBE MBE-->>S: POST initiateTransaction activate S S-->>MBE: SamsungPayTransaction deactivate S MBE-->>CSDK: SamsungPayTransaction deactivate MBE CSDK->>U: Payment Status end alt Google Pay Supported MFE->>U: Render Payment Button U-->>MFE: Tap "Google Pay" Button MFE-->>CSDK: button.onClick() CSDK->>U: Display Payment Sheet U-->>CSDK: Authorize Payment CSDK-->>MBE: POST /api/google-pay/create activate MBE MBE-->>S: POST initiateTransaction activate S S-->>MBE: GooglePayTransaction deactivate S MBE-->>CSDK: GooglePayTransaction deactivate MBE CSDK->>U: Payment Status end

Client-side Integration

SDK Integration

The integration can be sub-divided into three sections: installing the SDK, handling supported payment methods, and creating a payment button.

Installation

Run the following command to install the SDK and component package applicable to your client-side framework. The @stitch-money/web package should be used for non-React applications.

npm install @stitch-money/client @stitch-money/react

Import and initialise the SDK.

import { StitchWalletClientSdk } from "@stitch-money/client";

const stitchWalletClient = new StitchWalletClientSdk({});

Supported Payment Methods

Call supportedPaymentMethods to fetch a list of supported wallets on the device and/or browser. The PayWithWalletButton component can be used to render a payment button for any supported wallet. The method returns an array of WalletType, where the inclusion of an enum value indicates that the provider is applicable to the device/browser.

tip

supportedPaymentMethods should be used to inform the set of payment buttons to surface to the user in your application. For example, if supportedPaymentMethods returns ["SAMSUNG_PAY", "GOOGLE_PAY"] for an Android device with a card provisioned in both the Samsung Wallet and Google Pay apps, then you may choose to display one or both payment buttons using the pre-built component.

Creating Payment Button

Define callback functions for each wallet type to verify a payment session and create a payment. Note that a verify callback is only required for Apple Pay and Samsung Pay. These callbacks must be supplied as arguments along with related payment information to the onClick handler functions contained in the SDK. See the example below for representative callback function implementations.

Bind each PayWithWalletButton component (or wrapped web component) onclick event with the corresponding onClick handler function exported from the client-side SDK, e.g., onClickApplePaySessionHandler(...). Instantiate each handler function with the set of required and optional arguments.

Apple Pay Key Points

Both verify and createPayment callback functions are required.

The validationUrl is automatically retrieved within onClickApplePaySessionHandler once an Apple Pay web session has been requested (via user interaction with the payment button). This URL must be a domain that has been previously verified in order for validation to be successful and enable the payment process to continue.

Samsung Pay Key Points

Both verify and createPayment callback functions are required.

A callback or return URL must specified to handle the redirect after the payment has been verified by the user. When moving to this callback URL after user verification, the Samsung Pay Web checkout server adds the reference ID as a query parameter, called ref_id (i.e. https://your.callback.url?ref_id={referenceID}). For more information on consuming the reference identifier, visit the Samsung Pay developer documentation. This reference must be supplied on the server-side when creating a payment via the Stitch API.

Google Pay Key Points

Only a createPayment callback function is required.

Only information related to the display of the payment sheet is required; no billing or address information needs to be supplied.

Component Implementation

Import the PayWithWalletButton component and styles directly from the @stitch-money/react package to create the payment button.

import {
type PayWithWalletButtonProps,
PayWithWalletButton,
} from "@stitch-money/react";
import "@stitch-money/react/build/styles/css";

Sample Implementation

tip

While the following example assumes the use of React, the callback function logic is framework-agnostic and the sample code is valid for any integration.

import {
StitchWalletClientSdk,
WalletType,
type ApplePaySession,
type StitchTransaction,
} from "@stitch-money/client";
import {
PayWithWalletButton,
PayWithWalletButtonProps,
} from "@stitch-money/react";
import "@stitch-money/react/build/styles/css";
import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/router";

export interface WalletPayButtonProps {
amount: number;
reference: string;
disabled?: boolean;
}

export default function WalletPayButton({
amount,
reference,
disabled = false,
}: WalletPayButtonProps) {
const router = useRouter();
const [supportedMethods, setSupportedMethods] = useState<WalletType[]>([]);
const [selectedMethod, setSelectedMethod] = useState<WalletType | null>(null);
const stitchWalletClient = new StitchWalletClientSdk({});

useEffect(() => {
async function getSupportedPaymentMethods() {
const result = await stitchWalletClient.supportedPaymentMethods()
setSupportedMethods(result);
}
getSupportedPaymentMethods();
}, []);

const createApplePayPaymentCallback = useCallback(
async (paymentToken: unknown) => {
const response = await fetch(
`/api/wallet/apple-pay/create`,
{
method: "POST",
body: JSON.stringify({
paymentToken,
amount: {
quantity: amount,
currency: "ZAR",
},
externalReference: reference,
}),
}
);
const transaction = (await response.json()) as StitchTransaction;
if (transaction.status === "TransactionSuccess") {
router.push("/success");
}
return { status: transaction.status };
},
[amount, router, selectedMethod]
);

const applePayVerifyCallback = useCallback(async (url: string) => {
const response = await fetch("/api/wallet/apple-pay/verify", {
method: "POST",
body: JSON.stringify({
validationUrl: url,
initiativeContext: window.location.hostname,
}),
});
const session = (await response.json()) as Promise<ApplePaySession>;
return session;
}, []);

const onClickApplePay = useCallback<
PayWithWalletButtonProps["onClick"]
>(() => {
setSelectedMethod(WalletType.ApplePay);
const applePaySessionHandler =
stitchWalletClient.onClickApplePaySessionHandler(
"ZAR",
amount,
"Stitch",
applePayVerifyCallback,
createApplePayPaymentCallback
);
try {
applePaySessionHandler();
} catch (error) {
console.error(`Error starting Apple Pay session: ${error}`);
}
}, [amount, applePayVerifyCallback, createApplePayPaymentCallback]);

if (supportedMethods.includes(WalletType.ApplePay)) {
return (
<>
<PayWithWalletButton
supportedMethods={[WalletType.ApplePay]}
onClick={onClickApplePay}
disabled={disabled}
total={`${amount}`}
/>
</>
);
}
}

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 describes integrating using the JavaScript SDK or directly via the Stitch API.

Stitch SDK

The integration can be sub-divided into two sections: installing the SDK, and defining server-side handlers.

Installation

Run the following command to install the SDK.

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 server-side SDK returns two functions when initialised. These must be invoked on your application server or backend-for-frontend. Create an API route (endpoint handler) on your server to invoke the verify function call for each wallet provider. This is only required for Apple Pay and Samsung Pay.

// api/payment-providers/stitch/apple-pay/verify.ts

export async function POST(request: Request) {
// retrieve the request body from the client-side `verify` callback
const { validationUrl, initiativeContext } = req.body

const displayName = "Merchant Name"
const verifyResponse = await walletPayClient.verify(
"APPLE_PAY",
validationUrl,
displayName,
initiativeContext
);
return verifyResponse;
}

Create an API route on your server to invoke the create function call for each wallet provider. The payment token (in the case of Apple Pay and Google Pay) contains the payment encryption and transaction data that must be transmitted to Stitch.

Key Points

For Samsung Pay payments, the reference identifier (ref_id) retrieved from the URL query parameters post-redirect must be supplied as the token argument instead of the fetched payment token.

Apple Pay and Google Pay endpoint handlers are functionally identical. Ensure that the correct wallet type is specified as an argument to the create function.

// api/payment-providers/stitch/apple-pay/create.ts

export async function POST(request: Request) {
// retrieve the paymentToken from the client-side `createPayment` callback
const { paymentToken } = req.body;

const nonce = generateNonce();
const quantity = 1;
const currency = "ZAR";
const reference = "REF"; // client-specified reference e.g. order number

const createPaymentResponse = await walletPayClient.create(
"APPLE_PAY",
paymentToken,
quantity,
currency,
nonce,
reference
);
return createPaymentResponse;
}

Direct API

The verify SDK function encapsulates two distinct Stitch API interactions for Apple Pay and Samsung Pay - the validateApplePayMerchant and verifySamsungPay mutations. These mutations must be called in the server-side verification API routes for each wallet provider and are required before a payment can be initiated.

The GraphQL API URL https://api.stitch.money/graphql can be used for all wallet requests (whether on test or live clients). Note that a Stitch client token with the scope transaction_initiate is required to validate wallet merchants, or initiate any wallet transactions, via the API.

Note

The intitiative field in the ValidateApplePayMerchantInput input object must always be set to web.

The sessionData and merchantSession objects in the Stitch API response must be returned unaltered by the server-side verify API endpoint handler.

initiateTransaction API

To create a wallet payment, a Stitch API initiateTransaction mutation call is required in order to initiate the payment. The mutation must be called in the server-side payment creation API routes for each wallet provider.

The input variable object must be constructed distinctly for each wallet provider to correctly replicate the interaction encapsulated by the create SDK function.

Caution

For Apple Pay and Google Pay payments, the payment token must be Base64-encoded. The Apple Pay payment token is a JavaScript object and is a serialised object for Google Pay.

Note

The state 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.

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.
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

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-