Android SDK - android-sdk.payable.lk | Create Issue
- Request and install Sandbox PAYable APP - Testing purpose
- Add the below repository into your project level
settings.gradle
orbuild.gradle
file.
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
- Add the below dependency into your module level
build.gradle
file.
implementation 'com.github.payable:payable-sdk-dev:3.6.0'
1. Import PAYable SDK packages.
import com.payable.sdk.Payable;
import com.payable.sdk.PayableListener;
import com.payable.sdk.PayableProgressListener;
import com.payable.sdk.PayableSale;
2. Implement PayableListener
and declare PAYable client in your class.
public class MainActivity extends AppCompatActivity implements PayableListener {
Payable payableClient;
@Override
boolean onPaymentStart(PayableSale payableSale){
return true;
}
@Override
void onPaymentSuccess(PayableSale payableSale){
}
@Override
void onPaymentFailure(PayableSale payableSale){
}
}
3. Create PAYable client with
Payable.createPayableClient(activity: Activity, client_id: String, client_name: String, api_key: String);
It should be declared inside
onCreate
method like below.
@Override
protected void onCreate(Bundle savedInstanceState) {
...
payableClient = Payable.createPayableClient(this, "1452", "FOOD_COURT", "C6DFA0B215B2CF24EF04794F718A3FC8");
}
4. Override onActivityResult
method and set the callback listener to handle the response.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
...
payableClient.handleResponse(requestCode, data);
}
5. On click listener call the method to start payment.
PayableSale payableSale = new PayableSale(sale_amount: Double, payment_method: Integer);
- Optional parameters ReadMe
payableSale.setReceiptEmail("[email protected]");
payableSale.setReceiptSMS("0110000000");
payableSale.setOrderTracking("invoice56");
payableSale.setTerminalId("1254");
- Start the payment intent
payableClient.startPayment(payableSale, this);
- Payment methods
Payable.METHOD_ANY
Payable.METHOD_CARD
Payable.METHOD_WALLET
Example:
- For the order tracking you need to pass the tracking number in json data as below.
PayableSale payableSale = new PayableSale( /* saleAmount */ 500, Payable.METHOD_CARD);
payableSale.setReceiptEmail("[email protected]");
payableSale.setReceiptSMS("0110000000");
payableSale.setOrderTracking("invoice56");
payableClient.startPayment(payableSale, /* PayableListener */ this);
- In order to choose a TID for the transaction, you can pass the terminal ID.
payableSale.setTerminalId("terminalId");
payable.getStatusCode();
payable.getSaleAmount();
payable.getCcLast4();
payable.getCardType();
payable.getTxId();
payable.getTerminalId();
payable.getMid();
payable.getIsEmv();
payable.getTxnStatus();
payable.getReceiptSMS();
payable.getReceiptEmail();
payable.getOrderTracking();
Payable.PAYABLE_REQUEST_CODE : 3569;
Payable.PAYABLE_STATUS_SUCCESS : 222;
Payable.PAYABLE_STATUS_NOT_LOGIN : 555;
Payable.PAYABLE_STATUS_FAILED : 0;
Payable.PAYABLE_INVALID_AMOUNT : 999;
Payable.PAYABLE_APP_NOT_INSTALLED : 888;
Payable.TXN_SWIPE : 0;
Payable.TXN_EMV : 1;
Payable.TXN_MANUAL : 2;
Payable.TXN_NFC : 3;
- If you want to receive the progress updates of the ongoing payment in background, you need to register progress listener using
registerProgressListener(listener)
and make sure you unregister the listener usingunregisterProgressListener()
method on activityonDestroy()
method to avoid memory leakage.
payableClient.registerProgressListener(new PayableProgressListener() {
@Override
public void onCardInteraction(int action, PayableSale payableSale) {
}
@Override
public void onPaymentAccepted(PayableSale payableSale) {
}
@Override
public void onPaymentRejected(PayableSale payableSale) {
}
});
Explanation for PayableProgressListener
interface.
onCardInteraction(int action, PayableSale payableSale)
- This method will be called in the background when the terminal listens to any card interactions such as ENV, SWIPE, and NFC, this will respond with your sale values and interacted action as
Payable.EMV, Payable.SWIPE, Payable.NFC
and -1 for any error on card interaction. You can get the error description usingpayableSale.getMessage()
method.
onPaymentAccepted(PayableSale payableSale)
- This method will be called in the background when the terminal accepts the card and proceed further.
onPaymentRejected(PayableSale payableSale)
- This method will be called in the background when the terminal rejects the card or throws any errors from servers.
@Override
protected void onDestroy() {
super.onDestroy();
payableClient.unregisterProgressListener();
}
When you need to request any event from PAYable you will have to register the event listener and unregister it on onDestroy
method when you are done.
payableClient.registerEventListener(new PayableEventListener() {
@Override
public void onProfileList(List<PayableProfile> payableProfiles) {
}
@Override
public void onVoid(PayableResponse payableResponse) {
}
});
@Override
protected void onDestroy() {
super.onDestroy();
payableClient.unregisterEventListener();
}
Method | Callback |
---|---|
boolean requestProfileList() |
onProfileList(List<PayableProfile> payableProfiles) |
boolean requestVoid(String txId, int cardType); |
onVoid(PayableResponse payableResponse) |
boolean requestTransactionStatus(String txId, int cardType) |
onTransactionStatus(PayableTxStatusResponse payableResponse) |
boolean requestTransactionStatusV2(String orderId, int cardType) |
onTransactionStatus(PayableTxStatusResponseV2 payableResponse) |
PayableProfile
String tid;
String name;
String currency;
Integer installment;
PAYableResponse
int status;
String txId;
String error;
PayableTxStatusResponse
String cardName;
String ccLast4;
double amount;
int cardType;
String time;
String orderTracking;
int txType;
int currencyType;
int installment;
String tid;
String mid;
String cardNo;
PayableTxStatusResponseV2
String txKeyId
String cardHolder
String ccLast4
BigDecimal amount
int cardType
Date serverTime
String approvalCode
int transactionStatus
public class MainActivity extends AppCompatActivity implements PayableListener {
EditText edtAmount, edtTracking, edtEmail, edtSMS, edtTxnId;
Button btnPayCard, btnPayWallet, btnPay, btnProfile, btnVoid, btnStatus;
TextView txtResponse, actTitle;
double saleAmount = 0;
String selectedProfile;
// 1. Declare Payable Client
Payable payableClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edtAmount = findViewById(R.id.edtAmount);
edtTracking = findViewById(R.id.edtTracking);
edtEmail = findViewById(R.id.edtEmail);
edtSMS = findViewById(R.id.edtSMS);
edtTxnId = findViewById(R.id.edtTxnId);
btnPayCard = findViewById(R.id.btnPayCard);
btnPayWallet = findViewById(R.id.btnPayWallet);
btnPay = findViewById(R.id.btnPay);
btnProfile = findViewById(R.id.btnProfile);
btnVoid = findViewById(R.id.btnVoid);
btnStatus = findViewById(R.id.btnStatus);
txtResponse = findViewById(R.id.txtResponse);
actTitle = findViewById(R.id.actTitle);
actTitle.setText("Main Activity");
edtAmount.setFilters(AmountInputFilter.getFilter(this, 100000));
// 2. Set Payable Client
payableClient = Payable.createPayableClient(this, "1452", "FOOD_COURT", "C6DFA0B215B2CF24EF04794F718A3FC8");
btnPayCard.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hideSoftKeyboard(edtAmount);
// 3. Call your method
payableSale(Payable.METHOD_CARD);
}
});
btnPayWallet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hideSoftKeyboard(edtAmount);
// 3. Call your method
payableSale(Payable.METHOD_WALLET);
}
});
btnPay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
payableSale(Payable.METHOD_ANY);
}
});
btnProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
payableClient.requestProfileList();
}
});
/**
* Advanced Usage (Optional):
* If you want to receive the progress updates of the ongoing payment, you need to register a progress listener
* and make sure you unregister the listener using unregisterProgressListener() method on activity onDestroy() method
*
*/
payableClient.registerProgressListener(new PayableProgressListener() {
@Override
public void onCardInteraction(int action, PayableSale payableSale) {
Log.e("TEST_IMPL", "background: onCardInteraction: " + action + " => " + payableSale.toString());
updateTxtResponse("background: onCardInteraction => " + action);
Toast.makeText(getApplicationContext(), "background: onCardInteraction", Toast.LENGTH_SHORT).show();
}
@Override
public void onPaymentAccepted(PayableSale payableSale) {
Log.e("TEST_IMPL", "background: onPaymentAccepted: " + payableSale.toString());
updateTxtResponse("background: onPaymentAccepted => " + payableSale.getTxnTypeName());
Toast.makeText(getApplicationContext(), "background: onPaymentAccepted", Toast.LENGTH_SHORT).show();
}
@Override
public void onPaymentRejected(PayableSale payableSale) {
Log.e("TEST_IMPL", "background: onPaymentRejected => " + payableSale.toString());
updateTxtResponse("background: onPaymentRejected: " + payableSale.getMessage());
Toast.makeText(getApplicationContext(), "background: onPaymentRejected", Toast.LENGTH_SHORT).show();
}
});
/**
* Advanced Usage (Optional):
* If you want to make any requests to PAYable and get responses, register the event listener
* and make sure you unregister the listener using unregisterEventListener() method on activity onDestroy() method
*
*/
payableClient.registerEventListener(new PayableEventListener() {
@Override
public void onProfileList(final List<PayableProfile> payableProfiles) {
for (PayableProfile payableProfile : payableProfiles) {
updateFreshTxtResponse("tid: " + payableProfile.tid + " " + payableProfile.currency + " name: " + payableProfile.name + " inst: " + payableProfile.installment);
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
builder.setTitle("Select Profile");
String[] profileNames = new String[payableProfiles.size()];
for (int i = 0; i < payableProfiles.size(); i++) {
profileNames[i] = "tid: " + payableProfiles.get(i).tid + " " + payableProfiles.get(i).currency + " : name: " + payableProfiles.get(i).name + " inst: " + payableProfiles.get(i).installment;
}
builder.setItems(profileNames, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
selectedProfile = payableProfiles.get(which).tid;
btnProfile.setText("Selected Profile: " + selectedProfile);
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
@Override
public void onVoid(PayableResponse payableResponse) {
updateFreshTxtResponse("onVoid: " + payableResponse.status + " txId: " + payableResponse.txId + " error: " + payableResponse.error);
}
@Override
public void onTransactionStatus(PayableTxStatusResponse payableResponse) {
if (payableResponse.error != null) {
updateFreshTxtResponse("onTransactionStatus: " + payableResponse.status + " txId: " + payableResponse.txId + " error: " + payableResponse.error);
} else {
updateFreshTxtResponse("onTransactionStatus: " + payableResponse.toString());
}
}
@Override
public void onTransactionStatusV2(PayableTxStatusResponseV2 payableResponse) {
if (payableResponse.error != null) {
updateFreshTxtResponse("onTransactionStatus: " + payableResponse.status + " txId: " + " error: " + payableResponse.error);
} else {
updateFreshTxtResponse("onTransactionStatus: " + payableResponse.toFormattedString());
}
}
});
btnVoid.setOnClickListener(v -> {
if (!edtTxnId.getText().toString().isEmpty()) {
Picker.cardTypePicker(MainActivity.this, cardType -> payableClient.requestVoid(edtTxnId.getText().toString(), cardType));
}
});
btnStatus.setOnClickListener(v -> {
if (!edtTxnId.getText().toString().isEmpty()) {
Picker.cardTypePicker(MainActivity.this, cardType -> payableClient.requestTransactionStatus(edtTxnId.getText().toString(), cardType));
}
});
btnStatusV2.setOnClickListener(v -> {
if (!edtOrderId.getText().toString().isEmpty()) {
Picker.cardTypePicker(MainActivity.this, cardType -> payableClient.requestTransactionStatusV2(edtOrderId.getText().toString(), cardType));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
payableClient.unregisterProgressListener();
payableClient.unregisterEventListener();
}
private void payableSale(int paymentMethod) {
if (edtAmount.getText().toString().isEmpty()) {
Toast.makeText(this, "Amount is empty", Toast.LENGTH_SHORT).show();
return;
}
// 4. Convert sale amount to double from EditText
saleAmount = Double.parseDouble(edtAmount.getText().toString());
// 5. start the payment request to PAYable app with the callback listener
PayableSale payableSale = new PayableSale(saleAmount, paymentMethod);
if (!edtEmail.getText().toString().isEmpty()) {
payableSale.setReceiptEmail(edtEmail.getText().toString());
}
if (!edtSMS.getText().toString().isEmpty()) {
payableSale.setReceiptSMS(edtSMS.getText().toString());
}
if (!edtTracking.getText().toString().isEmpty()) {
payableSale.setOrderTracking(edtTracking.getText().toString());
}
if (selectedProfile != null) {
payableSale.setTerminalId(selectedProfile);
}
payableClient.startPayment(payableSale, this);
// Deprecated implementations
// payableClient.startPayment(saleAmount, paymentMethod, "{ \"ORDER_TRACKING\" : \"SDK-TEST\" }", this);
// payableClient.startPayment(saleAmount, paymentMethod, this);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 7. onActivityResult set the callback listener to handle the response
payableClient.handleResponse(requestCode, data);
}
// 8. onPaymentSuccess method
@Override
public boolean onPaymentStart(PayableSale payableSale) {
txtResponse.setText("foreground: onPaymentStart => " + payableSale.getSaleAmount());
return true;
}
// 8. onPaymentSuccess method
@Override
public void onPaymentSuccess(PayableSale payableSale) {
updateTxtResponse("foreground: onPaymentSuccess => " + payableSale.getTxId());
updateTxtResponse(payableSale);
edtTxnId.setText(payableSale.getTxId());
}
// 9. onPaymentFailure method
@Override
public void onPaymentFailure(PayableSale payableSale) {
updateTxtResponse("foreground: onPaymentFailure => " + payableSale.getMessage());
updateTxtResponse(payableSale);
}
// 10. Update..
private void updateTxtResponse(PayableSale payableSale) {
String responseText = "\nstatusCode: " + payableSale.getStatusCode() + "\n";
responseText += "responseAmount: " + payableSale.getSaleAmount() + "\n";
responseText += "ccLast4: " + payableSale.getCcLast4() + "\n";
responseText += "cardNo: " + payableSale.getCardNo() + "\n";
responseText += "cardType: " + payableSale.getCardType() + "\n";
responseText += "txId: " + payableSale.getTxId() + "\n";
responseText += "terminalId: " + payableSale.getTerminalId() + "\n";
responseText += "mid: " + payableSale.getMid() + "\n";
responseText += "txnType: " + payableSale.getTxnType() + "\n";
responseText += "txnStatus: " + payableSale.getTxnStatus() + "\n";
responseText += "receiptSMS: " + payableSale.getReceiptSMS() + "\n";
responseText += "receiptEmail: " + payableSale.getReceiptEmail() + "\n";
responseText += "paymentMethod: " + payableSale.getPaymentMethod() + "\n";
responseText += "message: " + payableSale.getMessage() + "\n";
responseText += "orderTracking: " + payableSale.getOrderTracking() + "\n";
updateTxtResponse(responseText);
}
private void updateTxtResponse(String message) {
txtResponse.setText(txtResponse.getText().toString() + "\n" + message);
}
private void updateFreshTxtResponse(String message) {
txtResponse.setText("");
updateTxtResponse(message);
}
protected void hideSoftKeyboard(EditText input) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(input.getWindowToken(), 0);
}
}
PAYable SDK Android Integration