The required steps and settings to perform the app to app integration with SmartPOS, are described throughout this section.
Step 1: Create Intent to call the SmartPOS app
Step 2: Define the object class MessageToSend
Step 3: Get response from SmartPOS
Step 1: Create Intent to call the SmartPOS app
The call to the SmartPOS app is made through an Intent which contains a bundle with the necessary information. The data sent to the SmartPOS can be viewed in the following code example:
private Intent createPendingIntent(String reference, String value, String apiToken, String apiTokenId, String gratuityAmount){
Intent launchIntent = new Intent();
//Package of Smartpos that will be called
launchIntent.setClassName("pt.sibs.android.mpos.sibsPagamentosQLY.NexGo”, "pt.sibs.android.mpos.sibsPagamentosQLY.NexGo.activities.MainActivity");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(launchIntent);
// create a json with value and reference
MessageToSend messageToSend = new MessageToSend();
value = value.replaceAll("[^\\d.]", "");
messageToSend.setAmmount(value);
messageToSend.setReference(reference);
messageToSend.setGratuityAmount(gratuityAmount);
Gson gson = new GsonBuilder().create();
String message = gson.toJson(messageToSend,MessageToSend.class);
// convert json to a Base64
byte[] bytes;
bytes = message.getBytes(StandardCharsets.UTF_8);
String base64msg = Base64.encodeToString(bytes, Base64.DEFAULT);
// create a bundle and intent to call mpos and send data over
Bundle data = new Bundle();
data.putString(PACKAGE_ID, BuildConfig.APPLICATION_ID);
data.putBoolean(REQUEST_RESPONSE, sw.isChecked());
data.putBoolean(BYPASS_INSERT_VALUE, bypassSw.isChecked());
data.putBoolean(EDITABLE_REFERENCE, editReferenceSw.isChecked());
data.putBoolean(CALL_IN_APP_FECHO, fechoSw.isChecked());
data.putString(API_TOKEN, apiToken);
data.putString(API_TOKEN_ID, apiTokenId);
data.putString(BASE64REFERENCE,base64msg);
data.putInt(REQUEST_KEY, activityRequestCode);
launchIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
launchIntent.putExtra(DATA_MPOS, data);
return launchIntent;
}
The example above illustrates a method that, in the end, returns an Intent with the necessary information.
Initially the Intent is created and the “setClassName” method, the SmartPOS Package and the Activity to be called are configured – in the case above, the MainActivity.
Subsequently an object of the MessageToSend type is created. In this object, values are assigned to the reference and amount fields.
After creating the object and filling in the values of both fields, the object is converted to json, using the Gson lib, and then the encoding of the string json is made to Base64. After filling the object, we can create the Bundle to be passed along with the Intent. The Bundle must contain the following elements:
- A String with the Application ID of the app which is calling the SmartPOS;
- Boolean values indicating whether the app requires a response from the SmartPOS; allows to edit the amount and reference; whether it will execute a Closure instead of a Purchase;
- A String with the Base64-encoded JSON data;
- An Integer valued used in the StartActivity that will use the Intent created by this method.
After creating the Bundle, the Flag Activity Single Top flag is set on the Intent and the Bundle is added to the Intent, returning it to be used elsewhere.
The development and production packages will be made available to developers once the integration journey initiates.
Step 2: Define the object class MessageToSend
In this object, the following fields must be populated:
- amount: this field contains the operation amount and is represented in cents. Example: for a €10 purchase, the amount must be populated with ‘1000’. This field type is String;
- reference: this field informs the reference associated to the operation. It is of the String type, 25- character length (maximum). May contain alphanumeric values.
- gratuity value: the field contains the gratuity value and is represented in cents. Example: for a purchase with the gratuity value of 1€, the gratuity value must be populated with “100”. This field type is String.
class MessagetoSend{
@SerializedName("reference")
private String reference;
@SerializedName("ammount")
private String ammount;
void setReference(String reference){
this.reference = reference;
}
void setAmmount(String amount){
this.ammount = amount;
}
@SerializedName("gratuityAmount")
private String gratuityAmount;
void setReference(String reference){
this.reference = reference;
}
void setAmmount(String amount){
this.ammount = amount;
}
void setGratuityAmount(String gratuityAmount){
this.gratuityAmount = gratuityAmount;
}
}
Step 3: Get response from SmartPOS
After the execution of the operation, a response can be received from the SmartPOS, if the flag corresponding to the key “REQUEST_RESPONSE” marks the value true.
The following example illustrates how to read the response if it comes via onActivityResult or onNewIntent:
@Override
protected void onNewIntent(Intent intent) {
String status = "";
String errorCode = "";
String date = "";
String reference = "";
String amount = "";
String paymentJson = "";
String mbwayDataJson = "";
String rtExpDate = "";
String gratuityAmount = "";
PaymentCallInAppData paymentCallInAppData = new PaymentCallInAppData();
MBWayCallInAppData mbwayCallInAppData = new MBWayCallInAppData();
// Get response from mpos
if (intent != null && intent.getExtras() != null) {
if (intent.getExtras().containsKey(CALLIN_ERROR_KEY))
errorCode = intent.getExtras().getString(CALLIN_ERROR_KEY);
if (intent.getExtras().containsKey(CALLIN_STATUS_KEY))
status = intent.getExtras().getString(CALLIN_STATUS_KEY);
if (intent.getExtras().containsKey(CALLIN_DATE_KEY))
date = intent.getExtras().getString(CALLIN_DATE_KEY);
if (intent.getExtras().containsKey(CALLIN_AMOUNT_KEY))
amount = intent.getExtras().getString(CALLIN_AMOUNT_KEY);
if (intent.getExtras().containsKey(CALLIN_REF))
reference = intent.getExtras().getString(CALLIN_REF);
if (intent.getExtras().containsKey(CALLIN_PAYMENT_RESPONSE)) {
paymentJson = intent.getExtras().getString(CALLIN_PAYMENT_RESPONSE);
paymentCallInAppData = (PaymentCallInAppData) JsonBuilder.fromJson(paymentJson, PaymentCallInAppData.class);
}
if (intent.getExtras().containsKey(CALLIN_REFRESH_TOKEN_EXP_DATE))
rtExpDate = intent.getExtras().getString(CALLIN_REFRESH_TOKEN_EXP_DATE);
if (intent.getExtras().containsKey(CALLIN_GRATUITY_VALUE))
gratuityAmount = intent.getExtras().getString(CALLIN_GRATUITY_VALUE);
if(data.getExtras().containsKey(CALLIN_MBWAY_CLIENT_DATA)) {
mbWayClientDataJson = data.getExtras().getString(CALLIN_MBWAY_CLIENT_DATA);
if(data.getExtras().containsKey(CALLIN_MBWAY_CLIENT_DATA)) {
mbWayClientDataJson = data.getExtras().getString(CALLIN_MBWAY_CLIENT_DATA);
mbwayCallInAppData = (MBWayCallInAppData) JsonBuilder.fromJson(mbWayClientDataJson, MBWayCallInAppData.class);
Toast.makeText(getApplicationContext(), "STATUS1: "+status+"\nError: "+errorCode+
"\nAmount: "+ amount +"\nGratuity Value: "+gratuityAmount +"\nDate:
"+date+"\nReference: "+reference+"\nRT Exp: "+ rtExpDate+"\nPayment Data:
"+paymentJson, Toast.LENGTH_LONG).show();
}
super.onNewIntent(intent);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == activityRequestCode) {
String status = "";
String errorCode = "";
String date = "";
String reference = "";
String amount = "";
String paymentJson = "";
String mbwayDataJson = "";
String rtExpDate = "";
String gratuityAmount = "";
PaymentCallInAppData paymentCallInAppData = new PaymentCallInAppData();
MBWayCallInAppData mbwayCallInAppData = new MBWayCallInAppData();
if (data != null && data.getExtras() != null) {
}
}
}
Either case, an Intent is received containing a Bundle filled by the SmartPOS with the response data.
After validating that the Intent exists and contains the Bundle, the values of each Key will be obtained, if present.
The response returns 8 values, detailed on the following tables:
Values | Description | String type |
---|---|---|
errorCode | Corresponds to the error code (if any) obtained by the SmartPOS while performing the operation. | CALLIN_ERROR_KEY |
status | Informs the status of the operation performed by the SmartPOS, which can be: DeviceError Success Declined CommError Usercancelled UserTimeOut Missing Credentials | CALLIN_STATUS_KEY |
date | Informs the date when the operation was performed by the SmartPOS. | CALLIN_DATE_KEY |
amount | Corresponds to the value used in the operation performed in SmartPOS, can be used to compare with the value sent in the bundle which invoked the SmartPOS app. It is of String type. | CALLIN_AMOUNT_KEY |
reference | Corresponds to the reference used in the operation performed in the SmartPOS, can be used to compare with the value sent in the Bundle which invoked the SmartPOS app. | CALLIN_REF |
Payment data* | Corresponds to a JSON with the data of the payment operation performed by the SmartPOS and can be easily used when converted to a PaymentCallInAppData object. | CALLIN_PAYMENT_RESPONSE |
Token expiration date | Corresponds to the token’s expiration date timestamp. | CALLIN_REFRESH_TOKEN_EXP_DATE. |
MB WAY Client data* | Corresponds to a json with the MB WAY information used in the operation performed in the SmartPOS – TIN and email – that can be sent as a response to a payment with QR code. | CALLIN_MBWAY_CLIENT_DATA. |
Payment data*
The json has the following structure:
{
"authId": "002500",
"blikCode": “777523”,
"blikRef": “65282046555”,
"cardData": {
"appId": "A0000000031010",
"appLabel": "VISA CGD CL",
"bin": "412487",
"cardholderName": "",
"expirityDate": "22/08",
"issuerName": "Visa",
"maskedPAN": "************"
},
"errorMessage": null,
"isError": false,
"merchantData": {
"acceptorAddress": "Glória do Ribatejo",
"acceptorLocation": "Ribatejo",
"acceptorName": "Loja da Glória",
"aditionalText1": "INSERE V09 \nINSERE V09",
"merchantFiscalNumber": "774477447",
"merchantName": "COMERCIANTE DO LEGACY",
"terminal": "34937",
"terminalName": "Testes DEV"
},
"reference": "",
"transactionData": {
"amount": 0.88,
"apc": "89C08287DDD1D731",
"atc": "0230",
"date": "2022-04-08",
"isAutenticationByPin": false,
"isAutenticationBySignature": false,
"mid": "0000837900S5342",
"paymentType": "CARD_CHIP_CONTACTLESS",
"time": "10:50:49",
"trn": "000010482438”,
"tsi": "0000"
}
}
MB WAY Client data*
{
"fiscalIdentificationNumber": "123456789",
"email": “email_de_teste@sibs.com”
}
Name | Shape | Description |
---|---|---|
fiscalidentificationNumber | String | TIN |
String | Client’s email |
The following table refers to the json fields with the data of the payment transaction carried out by the SmartPOS:
Table 1: PaymentCallInAppData
Table 2: CardData
Table 3: MerchantData
Table 4: TransactionData
Table 5: TransactionData
PaymentCallInAppData
Name | Format | Description |
---|---|---|
authId | string | Authorization ID |
blikCode | string | Blik code |
blikRef | string | Blik reference |
cardData | CardData | Card Data |
errorMessage | string | Error message |
isError | string | Validates whether an error has occurred: ‘true’ / ‘false’ |
merchantData | MerchantData | Merchant Data |
reference | string | Reference |
transactionData | TransactionData | Transaction Data |
CardData
Name | Format | Description |
---|---|---|
appID | string | Card’s AID |
appLabel | string | Card Type ( Visa Electron) |
bin | string | Card BIN |
cardholderName | string | Cardholder name |
expirityDate | string | Card Expiry Date |
issuerName | string | Issuer Name |
maskedPAN | string | PAN partially / fully masked |
MerchantData
Name | Format | Description |
---|---|---|
acceptorAddress | string | Name of the town / location registered for the terminal |
acceptorLocation | string | Address registered for the terminal |
acceptorName | string | Merchant name registered for the terminal |
additionalText | string | Merchant’s additional text |
merchantFiscalNumber | string | Merchant’s Fiscal Number |
merchantName | string | Merchant Name |
terminal | string | Terminal Identification |
terminalName | string | Terminal designation |
TransactionData
Name | Format | Description |
---|---|---|
amount | Double | Payment amount |
apc | String | APC – Application Cryptogram |
TransactionData
Name | Format | Description |
---|---|---|
atc | string | ATC – Application Transaction Counter |
date | string | Transaction date (YYYY-MM-DD) |
isAutenticationByPin | boolean | Informs whether the authentication was with PIN: ‘true’ / ‘false’ |
isAutenticationBySignature | boolean | Informs whether the authentication was with signature: ‘true’ / ‘false’ |
mid | string | Merchant unique identifier |
paymentType | string | Payment type, with the following possible values: NONE; MBWAY; CARD_MAGSTRIPE; CARD_CHIP_CONTACT; CARD_CHIP_CONTACTLESS; QRCODE; |
time | string | Transaction time (HH:MM:SS) |
trn | string | TRN – Transaction Reference Number |
tsi | string | TSI – Transaction Status Information |
The used keys are exemplified on the code below:
final static String DATA_MPOS = "DATA_MPOS"; //key with name of bundle
final static String PACKAGE_ID = "PACKAGE_ID"; //key with caller package id
final static String BASE64REFERENCE = "BASE64REFERENCE"; //key for base64 sent to mpos
final static String REQUEST_RESPONSE = "RETURN_VALUE_BOOLEAN"; //key with boolean indicating if response is required
final static String BYPASS_INSERT_VALUE = "lockAmountValue"; //indicates if the amount is editable in mpos
final static String EDITABLE_REFERENCE = "EDITABLE_REFERENCE"; //indicates if the reference is editable in mpos
final static String CALL_IN_APP_FECHO = "performAutomaticClose"; //boolean that if set true, executes "fecho"
final static String REQUEST_KEY = "REQUEST_KEY"; //activity request key
final static String CALLIN_ERROR_KEY = "CALL_IN_ERROR"; //key for response field : error
final static String CALLIN_STATUS_KEY = "CALL_IN_STATUS"; //key for response field : status
final static String CALLIN_AMOUNT_KEY = "CALL_IN_AMOUNT"; //key for response field: amount
final static String CALLIN_DATE_KEY = "CALL_IN_DATE"; //key for response field: date
final static String CALLIN_REF = "CALL_IN_REF"; //key for response field: reference
final static String CALLIN_PAYMENT_RESPONSE = "CALLIN_PAYMENT_RESPONSE"; //key for response field: payment data final static String
final static String CALLIN_REFRESH_TOKEN_EXP_DATE = "CALLIN_REFRESH_TOKEN_EXP_DATE"; //key for response field: token expiration date
final static String CALLIN_GRATUITY_VALUE = "CALLIN_GRATUITY_VALUE"; //Key for response field: gratuity value
final static String CALLIN_MBWAY_CLIENT_DATA = "CALLIN_MBWAY_CLIENT_DATA"; //Key for response field: mbway client data
Below you can find a table with the Used Keys and correspondent definition.
Used keys | Key definition |
---|---|
DATA_MPOS | Corresponds to the name of the Bundle used to call the SmartPOS app |
PACKAGE_ID | Contains the application ID of the app which is calling the SmartPOS |
BASE64REFERENCE | Corresponds to the value in base 64 of the JSON created from the object MessageToSend with the amount and reference values populated |
REQUEST_RESPONSE | Corresponds to the flag which indicated whether the app that is invoking the SmartPOS requires a response |
BYPASS_INSERT_VALUE | Key corresponding to the flag which indicated whether the app allows to edit the amount value |
EDITABLE_REFERENCE | Key corresponding to the flag which indicates whether the app allows to edit the reference |
REQUEST_KEY | Corresponds to the Int value used in the StartActivity that used the created intent |
CALLIN_ERROR_KEY | Used in case of response corresponding to the error (if any) obtained by the SmartPOS while performing the operation |
CALLIN_STATUS_KEY | Used in case of response and it informs the status of the operation performed by the SmartPOS (success, declined, etc.) |
CALLIN_AMOUNT_KEY | Used in case of response and corresponds to the amount of the operation performed in the SmartPOS |
CALLIN_DATE_KEY | Used in case of response and it informs the date when the operation was performed in the SmartPOS |
CALLIN_REF | Used in case of response and it contains the reference used in the operation performed in the SmartPOS |
CALL_IN_APP_FECHO | Corresponds to the flag indicating whether the app will perform a closure (“fecho”, in Portuguese) instead of a purchase |
CALLIN_PAYMENT_RESPONSE | Key used in case of a response, corresponding to the data of the payment operation performed by the SmartPOS |
CALLIN_REFRESH_TOKEN_EXP_DATE | Key used in case of a response, corresponding to the timestamp of the SmartPOS session token’s expiry date |
CALLIN_GRATUITY_VALUE | Key used in case of a response, correspondent to the gratuity value |
CALLIN_MBWAY_CLIENT_DATA | Key used in case of a responses correspondent to the MB WAY information used in the operation performed in the SmartPOS |
API_TOKEN | Key used to export the authentication token of the payment app. This token was generated through the backoffice or the application. The token contains the information of the User who generated it. The token generation is done through the tab “Manage API Key”. This must be transmitted in JWT format (base64 with dot dividers, such as header. Body. Trailer). The token generated through the backoffice or the application is provided in the format expected by the payment application |
API_TOKEN_ID | Key used to transport the authentication ID. It is used by the partner application- The API_Token_ID is in string format. |
Here’s an example code for using the API_Token:
The API key menu allows the configuration of Single Sign On (SSO) authentication intended to allow the User a secure login to the partner application (such as business app or invoicing apps) without the need to login to the payment application.
On accessing this menu page, the User will be shown the list of API Keys that are currently active as per the following figure:
To create a new API Key, the user should use the “Add API Key” button, available at the top of the page. Clicking on this button opens a window where the user must enter the following data to create the token:
- Key Name (optional)
- Password (mandatory)
Since the “Key name” is an optional field, it does not need to be filled in. In these cases, a name will be automatically generated by the backend. This “key name” field is to help you identify the token in use.
After entering the required data, a success message will be displayed for token creation and a file with the token and the token ID will be automatically downloaded. This file has a JSON with the following structure:
There is a validation at the “Key Name” level. If the User tries to create a token with the name of an existing key, the following error message will be displayed: “A token with the specified if already exists, each token must have a unique name.”
The key can be renewed on the “Re-generate” butting, that is, this button creates a new key for a given API Token. The next steps will be to simply enter the account password, which will trigger the automatic download of the file with the re-generated token. Since it is a token obtained with an ephemeral key, it will be different from the originally generated token.
The Delete button shall be used to revoke an existing token. This functionality will cause the selected token to be deleted, rendering it invalid. For security reasons a warning message is displayed before the User starts the token deletion process.
If the action is confirmed, the token deletion process will start, and the user sill only need to enter the password to complete the process.
Once completed, the token will be deleted, hence becoming invalid for use in any application. The deleted token shall be removed from the list of active keys and cannot be re-generated.
Once the token is created, it can be used to authenticate the partner application, through the app to app call. As long as the token is valid, the User won’t be logged out of the payment apps and all the requests will be authenticated with the token.