Integrate SDK
Integrate with Tyro Embedded Payments SDK to accept in-person payments using a compatible Android device. You will first need to implement Account Authorisation. An open-source example app is available at https://github.com/tyro/tyro-tap-to-pay-sdk-android.
Overview of Embedded Payments Android SDK Flow
Integration
Github access
Tyro Embedded Payments SDK is distributed via Github Packages, so you will need a Github account.
Follow these steps to create a Personal Access Token (PAT).
A 'classic' token with (at least) public_repo
scope is sufficient.
Once you have created your PAT, you will need to reference it from your Android project.
You can do this using environment variables, as in the example below.
In settings.gradle add the Tyro repository:
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://maven.pkg.github.com/tyro/tyro-tap-to-pay-sdk-android")
credentials {
username = System.getenv("GITHUB_PACKAGES_USER")
password = System.getenv("GITHUB_PACKAGES_PASSWORD")
}
}
}
}
dependencyResolutionManagement {
repositories {
maven {
url 'https://maven.pkg.github.com/tyro/tyro-tap-to-pay-sdk-android'
credentials {
username System.getenv("GITHUB_PACKAGES_USER")
password System.getenv("GITHUB_PACKAGES_PASSWORD")
}
}
}
}
In build.gradle add the Tyro dependency:
val tyroSdkVersion by extra("<VERSION>")
dependencies {
// ...
debugImplementation("com.tyro:tyro-tap-to-pay-sdk-debug:$tyroSdkVersion")
releaseImplementation("com.tyro:tyro-tap-to-pay-sdk-release:$tyroSdkVersion")
}
ext { set('tyroSdkVersion', '<VERSION>') }
dependencies {
// ...
debugImplementation "com.tyro:tyro-tap-to-pay-sdk-debug:${tyroSdkVersion}"
releaseImplementation "com.tyro:tyro-tap-to-pay-sdk-release:${tyroSdkVersion}"
}
Accept tyroDebug build type
Tyro publishes two dependencies:
tyro-tap-to-pay-sdk-debug
tyro-tap-to-pay-sdk-release
The release
dependency includes some additional security checks.
Most notable of these is that it requires on-device developer mode to be disabled.
The debug
build published by Tyro does not have this requirement, making testing easier.
It is, however, obfuscated and non-debuggable.
You will need to configure your debug
build type to accept tyroDebug
as a fallback.
android {
...
buildTypes {
...
debug {
...
matchingFallbacks += listOf("tyroDebug")
}
}
}
android {
...
buildTypes {
...
debug {
...
matchingFallbacks.add("tyroDebug")
}
}
}
R8 Support
Tyro Embedded Payments SDK does not currently support R8 full mode.
You may need to include the following line in gradle.properties
.
android.enableR8.fullMode=false
Demonstration App
The demo app has three build flavors:
- stub
- dev
- prd
The app should run in stub
flavor out of the box.
To run against the development environment:
- Change the
applicationId
inbuild.gradle
tocom.tyro.taptopay.sdk.demo
. - Use the sample app keystore and keystore password you have been provided during onboarding.
- Implement authentication with Tyro on your own server.
To run in a production environment:
- Change the
applicationId
inbuild.gradle
to your own - Include your own keystore, and update the
signingConfigs
part ofbuild.gradle
with your keystore details - Export a public certificate from your keystore, and provide it to Tyro along with your
applicationId
See below for more detail on these requirements.
Verification data
Tyro requires the following in order to verify the integrity of your app. These must be provided even to run the app against the Tyro test environment.
- Your application ID
- Your upload public certificate
Application ID
This is the applicationId
as defined in your build.gradle
file.
android {
// ...
defaultConfig {
// ...
applicationId = "com.example.my.app" // <-
}
}
Public certificate
The public certificate is derived from the upload keystore specified in build.gradle
:
android {
// ...
signingConfigs {
create("my_signing_config") {
keyAlias = "my_key"
keyPassword = "p@ssw0rd"
storeFile = file("my.keystore")
storePassword = "p@ssw0rd"
}
}
}
Follow these instructions to create your own upload keystore if required. You can export the public certificate from the keystore using keytool:
keytool -export -keystore tyro.keystore -alias my_alias -rfc -file public.pem
Your server — add an endpoint to create a connection
When the Android App is first initialised, a request must be sent to your server to establish a Tyro Embedded Payments connection.
Upon receiving the client request, authenticate your user and send the request to Tyro with the readerId
in the request body (obtained from Account Authorisation).
The Embedded Payments connection response will return a connectionSecret
, this should be returned to your App.
// Node sample code
const express = require("express");
const app = express();
const axios = require('axios');
// ...
app.post("/create-connection", async (req, res) => {
const { userIdOrDeviceId } = req.body; // You can associate a user or device to the reader.
// You will manage the authentication between your server and App.
const readerId = await this.findReaderIdForUser(userIdOrDeviceId);
// Create a Embedded Payments connection by providing the location Id
const connectionResponse = await axios.post('https://api.tyro.com/connect/tap-to-pay/connections',
{
"readerId": readerId // e.g. 2688fcf2-44dd-4c72-88ac-79d0910f2933
},
{
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer exampleJwt'
}
});
res.send({
connectionSecret: connectionResponse.connectionSecret
});
});
Implement ConnectionProvider
The ConnectionProvider is responsible for fetching the Tyro connection secret from your server. The following example uses a Ktor client and kotlinx serialisation.
class MyConnectionProvider: ConnectionProvider {
@Serializable
private data class MyResponse(
val connectionSecret: String
)
private val client = HttpClient(CIO) {
install(ContentNegotiation) { json() }
}
override suspend fun createConnection(): String {
val url = "https://<YOUR-API-DOMAIN>/create-connection"
val response: MyResponse = client.get(url).body()
return response.connectionSecret
}
}
Create an instance of TapToPaySdk
Define the sdk as a variable in your Application
class and create an instance inside the onCreate()
method.
class SdkDemoApplication : Application() {
lateinit var tapToPaySDK: TapToPaySdk
override fun onCreate() {
super.onCreate()
tapToPaySDK = createTapToPaySdk()
}
@Suppress("KotlinConstantConditions")
private fun createTapToPaySdk(): TapToPaySdk {
val tyroEnv: TyroEnv =
when (BuildConfig.FLAVOR) {
"stub" -> TyroEnvStub()
"dev" ->
TyroEnvDev(
connectionProvider = SdkDemoConnectionProvider(),
)
else ->
TyroEnvProd(
connectionProvider = SdkDemoConnectionProvider(),
)
}
return createInstance(tyroEnv, applicationContext, TyroOptions(TyroScreenOrientation.PORTRAIT)).apply {
setPosInfo(
PosInfo(
posName = "Demo",
posVendor = "Tyro Payments",
posVersion = "1.0",
siteReference = "Sydney",
),
)
}
}
}
There are three environments available:
- stub (TyroEnvStub)
- development (TyroEnvDev)
- production (TyroEnvProd)
The stub environment does not interact with the Tyro backend at all, so does not require a ConnectionProvider. It may be useful for UI development etc. Return values and delays can be customised to help with testing.
In the onCreate method of your activity
Important: your Activity will need to be a ComponentActivity (or one of its subclasses)
private lateinit var transactionLauncher: ActivityResultLauncher<TransactionRequest>
// ...
override fun onCreate(savedInstanceState: Bundle?) {
// ...
// register a handler for transaction results
tapToPaySdk.registerTransactionResultHandler(this) { transactionResult ->
when (transactionResult.status) {
TransactionStatus.TXN_SUCCESS -> handleTransactionSuccess(transactionResult)
else -> handleTransactionFailure(transactionResult)
}
}
// initialise the Tyro Embedded Payments SDK
// this could take some time - you will need to show a loading screen or similar
showLoadingScreen()
tapToPaySdk.init(this) { initResult ->
hideLoadingScreen()
when (initResult.status) {
InitStatus.INIT_SUCCESS -> handleInitSuccess(initResult)
else -> handleInitFailure(initResult)
}
}
}
Admin Settings
Create a button in your screen, use updateAdminSettings
method to start the admin settings activity.
This screen allows your POS administrators to set a mandatory refund password and additional settings in the future.
tapToPaySdk.updateAdminSettings(activity)
Making Payments
Start a new transaction
val transactionRequest = TransactionRequest(
type = TransactionType.TRANSACTION,
amountInCents = amountInCents,
reference = "my-unique-transaction-reference",
)
tapToPaySdk.startTransaction(activity, transactionRequest)
Start a new refund
val transactionRequest = TransactionRequest(
type = TransactionType.REFUND,
amountInCents = amountInCents,
reference = "my-unique-transaction-reference"
)
tapToPaySdk.startTransaction(activity, transactionRequest)
Register Webhooks
Webhook events are sent once a payment has occurred. Your server should listen to these events and handle them as required, for example to send a payment receipt email.
Tyro UI
A Tyro UI will be visible from when a transaction is initiated until it is complete. Please note final designs are still pending.