To integrate your own app with the Rabo SmartPin app, follow the below steps:
Set up
Step 1 - Apply for Rabo Smart Pay and Rabo SmartPin
If you are not already a Rabo Smart Pay customer, you need to apply for it:
- Start your application for one or more Rabo SmartPin card readers or Tap to Pay subscriptions through the Rabo Smart Pay dashboard.
- Follow the required steps to become a customer.
After your application is submitted and approved, you should receive an electronic contract . Tap to Pay can be used immediately.
You should receive the Rabo SmartPin card reader(s) within 5 business days.
Install the Rabo SmartPin app on the smartphone or tablet where your own app is available.
Tap to Pay requires:
- iPhone XS or higher with the latest iOS.
- Android device requires at least version 11.
- Android 11+ on devices are originally shipped with Android version 8 or higher.
- NFC technology should be available and enabled.
- Google Mobile Services should be available (in other words, the mobile device is GMS certified).
We recommend using the latest software version for devices.
- Test if you can initiate a debit card payment.
Do you already have a Rabo SmartPin card reader? Or a Tap to Pay subscription? You can skip the above steps.
If the payment is successful, activate app-in-app in the Rabo SmartPin app:
- Go to Settings.
- Choose Developer options.
Step 2 - Integrate Rabo SmartPin with your own app
You have the option to include the following fields from your own app:
- Amount
- Payment Id
- Transaction reference
- Payment method
Your user can fill in these fields for each payment in your own app or choose to have the application fill them in by default.
After the payment is made, your app receives back successful or failed payment data fields, including debit card receipt details.
This process is different for Android and iOS, For a comprehensive overview, see App-in-App with card reader demonstration and Rabo Smart Pin App-in-App screens demonstration.
Step 3 - Using the app-in-app link - Quick Reference Guide
For the initial transaction, enter your password in the Rabo SmartPin app. You are only required to do this once a day.
Payment flow:
- In your own app, enter the amount you want your customer to pay. Add a reference, if necessary.
- Tap Pay.
- You automatically enter the Rabo SmartPin app.
- Select the desired payment option. For example, the Rabo SmartPin card reader or Tap to Pay.
- If all is fine, you receive the Approved status and your payment is done.
Receipt
- After the payment is complete, tap To Checkout to return to your own app.
- The Transaction fields are automatically copied from the Rabo SmartPin app.
- In the Rabo SmartPin app Daily Totals, you should find a transaction summary, which is broken down by date and payment method. You also have the option here of resending the receipt to the customer after the transaction is done (accepted or declined)
If you have multiple outlets, card readers, or Tap to Pay subscriptions you can also filter these transactions.
Transactions made using the Rabo SmartPin app-in-app link can be recognized by the following icon:
If a payment reference is entered using the cash register system from the merchant that calls the app in app connection you can find the payment reference in the Daily Totals with the payments that have a transaction reference added.
Android integration
Initiating payments from a third-party app - Android
Request:
You can initiate a payment from a third-party app using the Intents mechanism. The following data can be included:
Var | Format | Description |
id | string | Mandatory, unique value that can be used by the merchant to identify the transaction |
amount | int | Mandatory, amount in cents |
callbackUrl | string | Mandatory when integrating using URL. The URL is used to provide status feedback. |
reference | string | Optional, payment reference (max length 255 characters) |
type | string | Optional, payment method. [“PIN”|”CASH”| “TAPTOPAY”] |
Response:
After the payment is complete, you receive feedback with the status of the payment with the following fields:
Merchant data, which we return:
id | string | As provided by the third-party app |
amount | int | As provided by the third-party app |
reference | string | As provided by the third-party app |
type | string | Payment method. [“PIN”|”CASH”| “TAPTOPAY”] |
Transaction data returned by Rabobank:
datetime | string | Date and time of payment (ISO8601) |
state | string | Payment status (see below) |
transactionId | string | Transaction ID |
terminalId | string | Pin-only, terminal ID |
cardType | string | Pin-only, card type |
AID | string | Pin-only, AID |
truncatedPan | string | Pin-only, card number |
authCode | string | Pin-only, authorization code |
errorCode | string | Pin-only, error code |
change | int | Cash only, change in cents |
The following statuses are used:
Status | Message |
APPROVED | payment is successful |
DECLINED | payment failed |
PENDING | payment is pending, check the daily totals in the Rabo SmartPin app for payment status |
CANCELLED | the retailer cancelled payment |
DISABLED | third-party payments are not permitted under your contract |
INVALID | a mandatory field is missing |
IN_PROGRESS | another payment is already in progress |
REFUND_OFFLINE | refund not possible in restricted mode |
REFUND_FORBIDDEN | refund not permitted for logged-in user |
CASH_FORBIDDEN | cash transactions are not permitted under your contract |
TAPTOPAY_FORBIDDEN | Tap to Pay conditions have not been met/have yet to be met. |
Initiating payment through Intents
final Intent intent = new Intent(); intent.setAction(“nl.rabobank.smartpin.PAY”); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.putExtra(“id”, “abcdefg”); intent.putExtra(“amount”, 1234); intent.putExtra(“reference”, “Mijn betaling”); // Optional intent.putExtra(“type”, “PIN”); // Optional
if (getContext().getPackageManager().queryIntentActivities(intent, MATCH_DEFAULT_ONLY).size() > 0) { startActivityForResult(intent, SMARTPIN_ACTIVITY);
}
After the payment is received
private void parseOkResult(Intent data) {
PaymentFinishedFragment paymentFinishedFragment = new PaymentFinishedFragment(); String id = data.getStringExtra(“id”);
String reference = data.getStringExtra(“reference”);
String amount = data.getStringExtra(“amount”);
String type = data.getStringExtra(“type”);
String datetime = data.getStringExtra(“datetime”);
String state = data.getStringExtra(“state”);
String transactionId = data.getStringExtra(“transactionId”);
// For pin
String terminalId = data.getStringExtra(“terminalId”); String cardType = data.getStringExtra(“cardType”);
String AID = data.getStringExtra(“AID”);
String truncatedPan = data.getStringExtra(“truncatedPan”); String authCode = data.getStringExtra(“authCode”);
String errorCode = data.getStringExtra(“errorCode”);
// For cash
int change = data.getIntExtra(“change”);
// Handle transaction with above parameters }
private void parseCancelResult(Intent data) {
PaymentFinishedFragment paymentFinishedFragment = new PaymentFinishedFragment(); if (data != null) {
String id = data.getStringExtra(“id”);
String state = data.getStringExtra(“state”); String amount = data.getStringExtra(“amount”);
// Handle cancelled transaction with above parameters }
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SMARTPIN_ACTIVITY) { switch (resultCode) {
case Activity.RESULT_OK: parseOkResult(data); break;
case Activity.RESULT_CANCELED: parseCancelResult(data); break;
} }
super.onActivityResult(requestCode, resultCode, data); }
Initiating a payment using URL
Uri uri = Uri.parse("smartpin://payment?id="
+ System.currentTimeMillis() +
"&amount="+ amountInCents +
"&reference=" +reference +
"&type="+ paymentMethod +
"&showResult=false" +
"&url=thirdparty://result");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(mapIntent);
After payment is received
// In the url/activity that will be called by the smartpin app after a transaction
Uri data = getIntent().getData();
if (data != null) {
String id = data.getQueryParameter("id");
String state = data.getQueryParameter("state");
int amount = Integer.parseInt(data.getQueryParameter("amount"));
String type = data.getQueryParameter("type");
String datetime = data.getQueryParameter("datetime");
String reference = data.getQueryParameter("reference");
//For Pin
String transactionId = data.getQueryParameter("transactionId");
String cardType = data.getQueryParameter("cardType");
String AID = data.getQueryParameter("AID");
String truncatedPan = data.getQueryParameter("truncatedPan");
String authCode = data.getQueryParameter("authCode");
String errorCode = data.getQueryParameter("errorCode");
//For cash
int change = Integer.parseInt(data.getQueryParameter("change"));
// Handle transaction with above parameters }
private void parseCancelResult(Intent data) {
PaymentFinishedFragment paymentFinishedFragment = newPaymentFinishedFragment(); if (data != null) {
String id = data.getStringExtra(“id”);
String state = data.getStringExtra(“state”); String amount = data.getStringExtra(“amount”);
// Handle cancelled transaction with above parameters }
}
@Override
public void onActivityResult(intrequestCode, int resultCode, Intent data) {
if (requestCode == SMARTPIN_ACTIVITY) { switch(resultCode) {
case Activity.RESULT_OK: parseOkResult(data); break;
case Activity.RESULT_CANCELED: parseCancelResult(data); break;
} }
super.onActivityResult(requestCode, resultCode, data); }
iOS integration
Initiating payments from a third-party app - iOS
Request:
You can initiate a payment from a third-party app using a dedicated URL. The following data can be included:
Var | Format | Description |
id | string | Mandatory, unique value that can be used by the merchant to identify the transaction |
amount | int | Mandatory, amount in cents |
callbackUrl | string | Mandatory, URL used to provide status feedback |
reference | string | Optional, payment reference (max length 255 characters) |
type | string | Optional, payment method. [“PIN”|”CASH”| “TAPTOPAY”] |
Response:
After the payment is complete, you receive feedback with the status of the payment with the following fields:
Merchant data, which we return:
id | string | As provided by the third-party app |
amount | int | As provided by the third-party app |
reference | string | As provided by the third-party app |
type | string | Payment method. [“PIN”|”CASH”| “TAPTOPAY”] |
Transaction data returned by Rabobank:
datetime | string | Date and time of payment (ISO8601) |
state | string | Payment status (see below) |
transactionId | string | Transaction ID |
terminalId | string | Pin-only, terminal ID |
cardType | string | Pin-only, card type |
AID | string | Pin-only, AID |
truncatedPan | string | Pin-only, card number |
authCode | string | Pin-only, authorization code |
errorCode | string | Pin-only, error code |
change | int | Cash only, change in cents |
The following statuses are used:
Status | Message |
APPROVED | payment is successful |
DECLINED | payment failed |
PENDING | payment is pending, check the daily totals in the Rabo SmartPin app for payment status |
CANCELLED | the retailer cancelled payment |
DISABLED | third-party payments are not permitted under your contract |
INVALID | a mandatory field is missing |
IN_PROGRESS | another payment is already in progress |
REFUND_OFFLINE | refund not possible in restricted mode |
REFUND_FORBIDDEN | refund not permitted for logged-in user |
CASH_FORBIDDEN | cash transactions are not permitted under your contract |
TAPTOPAY_FORBIDDEN | cash transactions are not permitted under your contract |
Initiating a payment using URL
let url = URL(string: “smartpin://payment”)
if let url = url, let urlComponents = NSURLComponents(url: url, resolvingAgainstBaseURL: false) {
var parameters : [URLQueryItem] = []
parameters.append(URLQueryItem(name: “id”, value: “abcdefg”)) parameters.append(URLQueryItem(name: “amount”, value: “1234”)) parameters.append(URLQueryItem(name: “callbackUrl”, value: “thisappscheme://finished”)) parameters.append(URLQueryItem(name: “reference”, value: “Mijn betaling”)) // Optional parameters.append(URLQueryItem(name: “type”, value: “PIN”)) // Optional urlComponents.queryItems = parameters
if let compiledCallbackUrl = urlComponents.url {
if UIApplication.shared.canOpenURL(compiledCallbackUrl) {
// Perform the operation on SmartPin by calling the SmartPin URL scheme + parameters UIApplication.shared.openURL(compiledCallbackUrl)
} else {
// If application is not installed: display an error message
let alertController = UIAlertController(title: “Not installed”, message: “SmartPin application not installed, please install and try
again.”, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: “Okay”, style: .default, handler: nil)) self.present(alertController, animated: true, completion: nil)
} }
}
After the payment is received
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { if let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), urlComponents.host == “finished”
{
// Move the URL query paramets to a String dictionary var parameters : [String:String] = [:] if let queryItems = urlComponents.queryItems {
for item in queryItems {
if let value = item.value {
parameters[item.name] = value; }
} }
let id = parameters[“id”]
let reference = parameters[“reference”]
let amount = parameters[“amount”]
let type = parameters[“type”]
let datetime = parameters[“datetime”]
let state = parameters[“state”]
let transactionId = parameters[“transactionId”]
// For pin
let terminalId = parameters[“terminalId”]
let cardType = parameters[“cardType”]
let AID = parameters[“AID”]
let truncatedPan = parameters[“truncatedPan”]
let authCode = parameters[“authCode”]
let errorCode = parameters[“errorCode”]
// For cash let change = parameters[“change”]
// Handle transaction with above parameters return true }
}
Contact
Should you have any questions while these steps are being outlined or later on while using Rabo SmartPin, please contact the Rabo Smart Pay Support Team on telephone number +31 (0)88 727 11 57. Opening hours are weekdays from 8 AM to 6 PM and Saturdays from 9 AM to 5:30 PM.