├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── kamen_troshev.xml ├── encodings.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── mypos │ │ └── mypossdkdemo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── mypos │ │ │ └── mypossdkdemo │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable │ │ ├── button_selector.xml │ │ ├── button_shape.xml │ │ ├── button_shape_clicked.xml │ │ ├── button_shape_disabled.xml │ │ └── white_background.9.png │ │ ├── layout │ │ ├── activity_main.xml │ │ └── amount_dialog.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── pos_icon.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── mypos │ └── mypossdkdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── slavesdk ├── .gitignore ├── build.gradle └── slavesdk-2.1.6.aar /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developermypos/myPOS-SDK-Android/ec93365c1b43962a75f79ab0e00aeb944a365e9e/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/kamen_troshev.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | 39 | 40 | 44 | 45 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 18 | 19 | 20 | 40 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Android 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 80 | 81 | 82 | 83 | 84 | 1.7 85 | 86 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # myPOS SDK Android 2 | 3 | This repository provides a native Android SDK, which enables to integrate your Mobile App with myPOS Card terminals, processed by its platform, to accept card payments (including but not limited to VISA, Mastercard, UnionPay International, JCB, Bancontact). myPOS SDK Android communicates transparently to the card terminal(s) via Bluetooth. To process checkout SDK provides management of the terminal to complete all the steps for transaction processing, return or refund, card storage for recurring transactions, and communicates to the application transaction status, card token, card masked PAN. 4 | 5 | No sensitive card data is ever passed through to or stored on the merchant's phone. All data is encrypted by the card terminal, which has been fully certified to the highest industry standards (PCI, EMV I & II, Visa, MasterCard & Amex). 6 | 7 | ### Prerequisites 8 | 9 | 1. Merchant account on [www.myPOS.eu](https://www.mypos.eu/) (or received a test account). 10 | 2. Received myPOS terminal 11 | 3. Requested Access [Developers myPOS](http://developers.mypos.eu) site. 12 | 4. Deployment Target Android 4.0.3 or later. 13 | 5. Android SDK Platform 25 or later. 14 | 6. Android SDK Build-tools version 25.0.0 or later. 15 | 7. Android Device. 16 | 17 | ### Table of Contents 18 | 19 | * [Integration](#integration) 20 | 21 | * [Installation](#installation) 22 | 23 | * [Initialization](#initialization) 24 | 25 | * [Connect to terminal](#connect-to-terminal) 26 | 27 | * [Attach connection listener](#attach-connection-listener) 28 | 29 | * [Attach pos ready listener](#attach-pos-ready-listener) 30 | 31 | * [Send E-Receipt](#send-e-receipt) 32 | 33 | * [Make payment](#make-payment) 34 | 35 | * [Handle payment result](#handle-payment-result) 36 | 37 | * [Refund](#refund) 38 | 39 | * [Handle refund result](#handle-refund-result) 40 | 41 | * [Reprint last receipt](#reprint-last-receipt) 42 | 43 | * [Print random receipt](#print-random-receipt) 44 | 45 | * [Terminal mangement](#terminal-management) 46 | 47 | * [Activate terminal](#activate-terminal) 48 | 49 | * [Update terminal software](#update-terminal-software) 50 | 51 | * [Deactivate terminal](#deactivate-terminal) 52 | 53 | * [POS Info statuses](#pos-info-statuses) 54 | 55 | * [Change Package name of SDK](https://gist.github.com/developermypos/462ed6df93e562f7227e336d776050ca) 56 | 57 | # Integration 58 | 59 | ## Installation 60 | Add the repository to your gradle dependencies: 61 | 62 | ```java 63 | allprojects { 64 | repositories { 65 | mavenCentral() 66 | } 67 | } 68 | ``` 69 | 70 | Add the dependency to a module: 71 | 72 | ```java 73 | implementation 'com.mypos:slavesdk:2.1.7' 74 | ``` 75 | 76 | 77 | ## Initialization 78 | 79 | Initialize the MyPos components in your app: 80 | 81 | ```Java 82 | public class SampleApplication extends Application { 83 | 84 | private POSHandler mPOSHandler; 85 | 86 | @Override 87 | public void onCreate() { 88 | super.onCreate(); 89 | POSHandler.setCurrency(Currency.EUR); 90 | POSHandler.setApplicationContext(this); 91 | mPOSHandler = POSHandler.getInstance(); 92 | } 93 | ``` 94 | 95 | Optional settting for default receipt configuration is avaibale: 96 | 97 | ```Java 98 | POSHandler.setDefaultReceiptConfig(POSHandler.RECEIPT_PRINT_ONLY_MERCHANT_COPY); 99 | ``` 100 | 101 | If set the default receipt configuration can be removed: 102 | 103 | ```Java 104 | POSHandler.clearDefaultReceiptConfig(); 105 | ``` 106 | 107 | Optional setting for the language of the receipts is avaibale(default is Language.ENGLISH): 108 | 109 | ```Java 110 | POSHandler.setLanguage(Language.GERMAN); 111 | ``` 112 | 113 | isTerminalBusy() returns boolean to check if an operation is being performed at the moment: 114 | ```Java 115 | POSHandler.getInstance().isTerminalBusy(); 116 | ``` 117 | 118 | ## Connect to terminal 119 | 120 | Choose connection type: 121 | 122 | ```Java 123 | POSHandler.setConnectionType(ConnectionType.BLUETOOTH); // Use ConnectionType.USB for usb connection type 124 | ``` 125 | 126 | ```Java 127 | POSHandler.getInstance().connectDevice(context); 128 | ``` 129 | 130 | If connection type is set to BLUETOOTH, make sure needed permissions are given in order to discover available bluetooth devices. 131 | 132 | ```Java 133 | if (POSHandler.getInstance().checkPermissions(context)) { 134 | // continue... 135 | } else { 136 | // permissions request is sent... 137 | } 138 | ``` 139 | 140 | Handle permissions result. 141 | 142 | ```Java 143 | @Override 144 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 145 | if (requestCode == POSHandler.PERMISSIONS_REQUEST_CODE) { 146 | // check permissions result... 147 | } 148 | } 149 | ``` 150 | 151 | ## Attach connection listener 152 | 153 | ```Java 154 | mPOSHandler.setConnectionListener(new ConnectionListener() { 155 | @Override 156 | public void onConnected(final BluetoothDevice device) { 157 | // handle connected event here 158 | } 159 | }); 160 | ``` 161 | 162 | 163 | ## Attach pos ready listener 164 | 165 | ```Java 166 | mPOSHandler.setPOSReadyListener(new POSReadyListener() { 167 | @Override 168 | public void onPOSReady() { 169 | // now you can start a transaction 170 | } 171 | }); 172 | ``` 173 | 174 | ## Send E-Receipt 175 | 176 | In case you want to use email/phone receipt you have to choose POSHandler.RECEIPT_E_RECEIPT receipt configuration. 177 | 178 | Following listener will be fired immediately after transaction is approved: 179 | 180 | ```Java 181 | POSHandler.getInstance().setPOSCredentialsListener(new POSCredentialsListener() { 182 | @Override 183 | public void askForCredentials(final CredentialsListener listener) { 184 | listener.onCredentialsSet("email@example.com"); // instead of email you can pass a phone number 185 | } 186 | }); 187 | ``` 188 | 189 | ## Make payment 190 | 191 | Once initialization is completed, you can start using the myPOS SDK Android to accept card payments. 192 | 193 | Variant 1. 194 | Payment via internal SDK activity: 195 | Amount and transaction reference are optional parameters and can be set as null. 196 | 197 | ```Java 198 | mPOSHandler.openPaymentActivity( 199 | MainActivity.this /*activity*/, 200 | REQUEST_CODE_MAKE_PAYMENT /*requestCode*/, 201 | "10.50" /*amount*/, 202 | UUID.randomUUID().toString()/*transaction reference*/ 203 | ); 204 | ``` 205 | 206 | Variant 2. 207 | Payment via direct SDK method: 208 | Transaction reference is optional parameter and can be set as null. 209 | 210 | ```Java 211 | mPOSHandler.purchase( 212 | "10.50" /*amount*/, 213 | UUID.randomUUID().toString() /*transaction reference*/, 214 | POSHandler.RECEIPT_PRINT_AUTOMATICALLY /*receipt configuration*/ ); 215 | ); 216 | ``` 217 | 218 | ## Handle payment result 219 | 220 | Variant 1. 221 | Payment via internal SDK activity: 222 | 223 | ```Java 224 | protected void onActivityResult(int requestCode, int resultCode, Intent data){ 225 | if( requestCode == REQUEST_CODE_MAKE_PAYMENT && resultCode == RESULT_OK) { 226 | TransactionData transactionData = data.getParcelableExtra(POSHandler.INTENT_EXTRA_TRANSACTION_DATA); 227 | // Handle the response here 228 | } 229 | } 230 | ``` 231 | 232 | Variant 2. 233 | Payment via direct SDK method: 234 | 235 | ```Java 236 | mPOSHandler.setPOSInfoListener(new POSInfoListener() { 237 | @Override 238 | public void onPOSInfoReceived(final int command, final int status, final String description) { 239 | // Handle the response here 240 | } 241 | 242 | @Override 243 | public void onTransactionComplete(final TransactionData transactionData) { 244 | // Handle the response here 245 | } 246 | }); 247 | 248 | POSHandler.getInstance().setTransactionClearedListener(new PosTransactionClearedListener() { 249 | @Override 250 | public void onComplete(int phStatus) { 251 | // transaction is cleared and fully completed, terminal is ready for new operations 252 | } 253 | }); 254 | ``` 255 | See [POS Info statuses](#pos-info-statuses) for more information 256 | 257 | ## Refund 258 | 259 | With refund host application could initiate refund transaction to the customers’ card account with the specified amount. 260 | 261 | Variant 1. 262 | Refund via internal SDK activity: 263 | Amount and transaction reference are optional parameters and can be set as null. 264 | 265 | ```Java 266 | mPOSHandler.openPaymentActivity( 267 | MainActivity.this /*activity*/, 268 | REQUEST_CODE_MAKE_REFUND /*requestCode*/, 269 | "10.50" /*amount*/, 270 | UUID.randomUUID().toString()/*transaction reference*/ 271 | ); 272 | ``` 273 | 274 | Variant 2. 275 | Refund via direct SDK method: 276 | Transaction reference is optional parameter and can be set as null. 277 | 278 | ```Java 279 | mPOSHandler.refund( 280 | "10.50" /*amount*/, 281 | UUID.randomUUID().toString() /*transaction reference*/, 282 | POSHandler.RECEIPT_PRINT_AUTOMATICALLY /*receipt configuration*/ ); 283 | ); 284 | ``` 285 | 286 | ## Handle refund result 287 | 288 | Variant 1. 289 | Refund via internal SDK activity: 290 | 291 | ```Java 292 | @Override 293 | protected void onActivityResult(int requestCode, int resultCode, Intent data){ 294 | if( requestCode == REQUEST_CODE_MAKE_REFUND && resultCode == RESULT_OK) { 295 | TransactionData transactionData = data.getParcelableExtra(POSHandler.INTENT_EXTRA_TRANSACTION_DATA); 296 | // Handle the response here 297 | } 298 | } 299 | ``` 300 | 301 | Variant 2. 302 | Refund via direct SDK method: 303 | 304 | ```Java 305 | mPOSHandler.setPOSInfoListener(new POSInfoListener() { 306 | @Override 307 | public void onPOSInfoReceived(final int command, final int status, final String description) { 308 | // Handle the response here 309 | } 310 | 311 | @Override 312 | public void onTransactionComplete(final TransactionData transactionData) { 313 | // Handle the response here 314 | } 315 | }); 316 | 317 | POSHandler.getInstance().setTransactionClearedListener(new PosTransactionClearedListener() { 318 | @Override 319 | public void onComplete(int phStatus) { 320 | // transaction is cleared and fully completed, terminal is ready for new operations 321 | } 322 | }); 323 | ``` 324 | See [POS Info statuses](#pos-info-statuses) for more information 325 | 326 | ## Reprint last receipt 327 | 328 | With this method host application could request reprint of last transaction slip. 329 | 330 | ```Java 331 | mPOSHandler.reprintReceipt(); 332 | ``` 333 | 334 | ## Print random receipt 335 | 336 | Check if the connected myPOS device has a printer hardware: 337 | 338 | ```Java 339 | mPOSHandler.hasPrinter() 340 | ``` 341 | 342 | Printing an external receipt is performed by passing a ReceiptData object to the printReceipt() method 343 | 344 | ```Java 345 | ReceiptData receiptData = new ReceiptData(); 346 | receiptData.addLogo(1 /*Logo index*/); 347 | receiptData.addEmptyRow(); 348 | receiptData.addRow( 349 | "HEAD" /*text*/, 350 | ReceiptData.Align.CENTER, /* Enum align setting (LEFT, CENTER, RIGHT) */ 351 | ReceiptData.FontSize.DOUBLE /* Enum font size setting (SINGLE, DOUBLE) */ 352 | ); 353 | mPOSHandler.printReceipt(receiptData); 354 | ``` 355 | 356 | # Terminal management 357 | 358 | ## Activate terminal 359 | 360 | Before using terminal for a first time the SDK has to initiate Terminal activation, which will setup terminal for processing transaction, setting up Terminal ID, Merchant ID etc. 361 | 362 | ```Java 363 | mPOSHandler.activate(); 364 | ``` 365 | 366 | ## Update terminal software 367 | 368 | Each time terminal processing transaction, processor host checks for existing pending updates, and inform terminal if any. In that case by this method software update is activated, and terminal is going in the update mode. 369 | 370 | ```Java 371 | mPOSHandler.update(); 372 | ``` 373 | 374 | ## Deactivate terminal 375 | 376 | ```Java 377 | mPOSHandler.deactivate(); 378 | ``` 379 | 380 | ## POS Info statuses 381 | 382 | - POS_STATUS_PENDING_USER_INTERACTION 383 | POS terminal received Purchase or Refund operation. Waiting for user to provide card for the operation. 384 | 385 | - POS_STATUS_USER_CANCEL 386 | Current operation is terminated due user has cancelled it manually from the POS terminal. 387 | 388 | - POS_STATUS_INTERNAL_ERROR 389 | Current operation is terminated due internal error has occured. 390 | 391 | - POS_STATUS_TERMINAL_BUSY 392 | Current operation is terminated due POS terminal is busy with another operation. 393 | 394 | - POS_STATUS_UNSUPPORTED_SDK_VERSION 395 | Current operation is terminated due POS terminal version is not compatiable with myPOS SDK version. 396 | 397 | - POS_STATUS_NO_UPDATE_FOUND 398 | Operation Update is terminated due no update is available for the POS terminal. 399 | 400 | - POS_STATUS_MANDATORY_UPDATE 401 | Current operation is terminated due mandatory update is necessary. Update operation is performed automatically. 402 | 403 | - POS_STATUS_OPTIONAL_UPDATE 404 | No operation is performed after this status. An optional update is available for the POS terminal. 405 | 406 | - POS_STATUS_POS_UPDATING 407 | Terminal received an Update operation and started the procedure. 408 | 409 | - POS_STATUS_ACTIVATION_REQUIRED 410 | Current operation is terminated due POS terminal is not activated. It is necessary to activate the POS terminal in order to perform operations. 411 | 412 | - POS_STATUS_PROCESSING 413 | This status informs that a communication with the Host is performed on operation Purchase, Refund, Activate or Deactivate. 414 | 415 | - POS_STATUS_DEACTIVATION_NOT_COMPLETED 416 | Operation Deactivate finished unsuccessfully. 417 | 418 | - POS_STATUS_ACTIVATION_NOT_REQUIRED 419 | Operation Activate is terminated due POS terminal is already activated. 420 | 421 | - POS_STATUS_ACTIVATION_NOT_COMPLETED 422 | Operation Activate finished unsuccessfully. 423 | 424 | - POS_STATUS_WRONG_ACTIVATION_CODE 425 | Operation Activate is terminated due wrong activation code. 426 | 427 | - POS_STATUS_WRONG_DEACTIVATION_CODE 428 | Operation Deactivate is terminated due wrong deactivation code. 429 | 430 | - POS_STATUS_WAIT_ACTIVATION_CODE 431 | POS terminal received Activate operation and is waiting for user to provide an activation code. 432 | 433 | - POS_STATUS_WAIT_DEACTIVATION_CODE 434 | POS terminal received Dectivate operation and is waiting for user to provide an deactivation code. 435 | 436 | - POS_STATUS_UPDATE_NOT_COMPLETED 437 | Operation Update finished unsuccessfully. 438 | 439 | - POS_STATUS_TRANSACTION_NOT_FOUND 440 | When performing operation Reprint last receipt. Last transaction is not found and the operation is terminated. 441 | 442 | - POS_STATUS_NO_PRINTER_AVAILABLE 443 | Current operation(Print or Reprint last receipt) is terminated due POS device has no printer hardware. 444 | 445 | - POS_STATUS_NO_PAPER 446 | Current operation(Print or Reprint last receipt) is terminated due no paper is available in the POS terminal. 447 | Current operation(Purchase or Refund) completed successfully, but receipt won't be printed due no paper is available in the POS terminal. 448 | 449 | - POS_STATUS_WRONG_AMOUNT 450 | Current operation is terminated due wrong amount is provided to Purchase or Refund operation. 451 | 452 | - POS_STATUS_NO_CARD_FOUND 453 | Current operation is terminated due no card is provided. 454 | 455 | - POS_STATUS_NOT_SUPPORTED_CARD 456 | The provided card is not supported. POS terminal is waiting for supported card. 457 | 458 | - POS_STATUS_CARD_CHIP_ERROR 459 | Current operation is terminated due card chip reading failed. 460 | 461 | - POS_STATUS_INVALID_PIN 462 | Invalid PIN. POS Terminal is waiting for another PIN. 463 | 464 | - POS_STATUS_MAX_PIN_COUNT_EXCEEDED 465 | Current operation is terminated due wrong PINs count has exceeded. 466 | 467 | - POS_STATUS_PIN_CHECK_ONLINE 468 | This status informs that PIN validation is performed online. Current operation continue. 469 | 470 | - POS_STATUS_SUCCESS_ACTIVATION 471 | Operation Activate finished with success. 472 | 473 | - POS_STATUS_SUCCESS_DEACTIVATION 474 | Operation Dectivate finished with success. 475 | 476 | - POS_STATUS_SUCCESS_UPDATE 477 | Operation Update finished with success. 478 | 479 | - POS_STATUS_SUCCESS_PURCHASE 480 | Operation Purchase finished with success. 481 | 482 | - POS_STATUS_SUCCESS_REFUND 483 | Operation Refund finished with success. 484 | 485 | - POS_STATUS_SUCCESS_REPRINT_RECEIPT 486 | Operation Reprint last receipt finished with success. 487 | 488 | - POS_STATUS_SUCCESS_PRINT_RECEIPT 489 | Operation Print finished with success. 490 | 491 | - POS_STATUS_DOWNLOADING_CERTIFICATES_IN_PROGRESS 492 | This status informs that the SDK is downloading certificates from the POS Terminal. 493 | 494 | - POS_STATUS_DOWNLOADING_CERTIFICATES_COMPLETED 495 | Certificated downloading is completed successfully. 496 | 497 | - POS_STATUS_INCORRECT_PRINT_DATA 498 | Operation Print is terminated due incorrect print data is provided. 499 | 500 | - POS_STATUS_INCORRECT_LOGO_INDEX 501 | Operation Print is terminated due incorrect logo index is provided. 502 | 503 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 32 5 | buildToolsVersion '30.0.3' 6 | defaultConfig { 7 | applicationId "eu.leupau.mypossdkdemo" 8 | minSdkVersion 15 9 | targetSdkVersion 32 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | testImplementation 'junit:junit:4.13.2' 25 | implementation 'androidx.appcompat:appcompat:1.4.1' 26 | implementation 'com.google.android.material:material:1.6.0' 27 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 28 | implementation 'androidx.gridlayout:gridlayout:1.0.0' 29 | implementation 'androidx.cardview:cardview:1.0.0' 30 | implementation project(':slavesdk') 31 | } 32 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/mypos/mypossdkdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.mypos.mypossdkdemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("eu.leupau.mypossdkdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/mypos/mypossdkdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.mypos.mypossdkdemo; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.app.AlertDialog; 6 | import android.bluetooth.BluetoothDevice; 7 | import android.content.BroadcastReceiver; 8 | import android.content.Context; 9 | import android.content.Intent; 10 | import android.content.IntentFilter; 11 | import android.content.pm.PackageManager; 12 | import android.os.Build; 13 | import android.os.Bundle; 14 | import android.view.View; 15 | import android.widget.Button; 16 | import android.widget.TextView; 17 | import android.widget.Toast; 18 | 19 | import androidx.core.content.ContextCompat; 20 | 21 | import com.mypos.slavesdk.ConnectionListener; 22 | import com.mypos.slavesdk.ConnectionType; 23 | import com.mypos.slavesdk.Currency; 24 | import com.mypos.slavesdk.Language; 25 | import com.mypos.slavesdk.POSHandler; 26 | import com.mypos.slavesdk.POSInfoListener; 27 | import com.mypos.slavesdk.ReceiptData; 28 | import com.mypos.slavesdk.TransactionData; 29 | 30 | import java.util.UUID; 31 | 32 | public class MainActivity extends Activity implements View.OnClickListener{ 33 | private static final int REQUEST_CODE_MAKE_PAYMENT = 1; 34 | private static final int REQUEST_CODE_MAKE_REFUND = 2; 35 | 36 | 37 | private static final int PERMISSION_COARSE_LOCATION = 1; 38 | 39 | private TextView mStatus; 40 | private TextView mTerminalType; 41 | private Button mConnectBtn; 42 | private Button mPurchaseBtn; 43 | private Button mRefundBtn; 44 | private Button mDeactivateBtn; 45 | private Button mActivateBtn; 46 | private Button mUpdateBtn; 47 | private Button mReprintBtn; 48 | private Button mPrintBtn; 49 | 50 | private POSHandler mPOSHandler; 51 | 52 | private Toast mToast; 53 | 54 | @Override 55 | protected void onCreate(Bundle savedInstanceState) { 56 | super.onCreate(savedInstanceState); 57 | setContentView(R.layout.activity_main); 58 | 59 | mStatus = (TextView) findViewById(R.id.status); 60 | mTerminalType = (TextView) findViewById(R.id.terminal_connection_type); 61 | mConnectBtn = (Button) findViewById(R.id.connect_btn); 62 | mPurchaseBtn = (Button) findViewById(R.id.purchase_btn); 63 | mRefundBtn = (Button) findViewById(R.id.refund_btn); 64 | mDeactivateBtn = (Button) findViewById(R.id.deactivate_btn); 65 | mActivateBtn = (Button) findViewById(R.id.activate_btn); 66 | mUpdateBtn = (Button) findViewById(R.id.update_btn); 67 | mReprintBtn = (Button) findViewById(R.id.reprint_receipt_btn); 68 | mPrintBtn = (Button) findViewById(R.id.print_receipt_btn); 69 | 70 | mConnectBtn.setOnClickListener(this); 71 | mPurchaseBtn.setOnClickListener(this); 72 | mRefundBtn.setOnClickListener(this); 73 | mDeactivateBtn.setOnClickListener(this); 74 | mActivateBtn.setOnClickListener(this); 75 | mUpdateBtn.setOnClickListener(this); 76 | mReprintBtn.setOnClickListener(this); 77 | mPrintBtn.setOnClickListener(this); 78 | 79 | ( (TextView) findViewById(R.id.version)).setText("v. " + POSHandler.SDK_VERSION); 80 | 81 | POSHandler.setConnectionType(ConnectionType.BLUETOOTH); 82 | POSHandler.setCurrency(Currency.EUR); 83 | POSHandler.setLanguage(Language.ENGLISH); 84 | POSHandler.setApplicationContext(this); 85 | POSHandler.setDefaultReceiptConfig(POSHandler.RECEIPT_PRINT_AUTOMATICALLY); 86 | mPOSHandler = POSHandler.getInstance(); 87 | 88 | setEnabled(false); 89 | 90 | checkPermissions(); 91 | 92 | registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); 93 | 94 | setPosInfoListener(); 95 | 96 | mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT); 97 | } 98 | 99 | @Override 100 | public void onResume(){ 101 | super.onResume(); 102 | setConnectionListener(); 103 | } 104 | 105 | @Override 106 | public void onDestroy(){ 107 | if( mReceiver != null ) 108 | unregisterReceiver(mReceiver); 109 | super.onDestroy(); 110 | } 111 | 112 | private void checkPermissions(){ 113 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 114 | requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_COARSE_LOCATION); 115 | } 116 | } 117 | 118 | @Override 119 | public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { 120 | switch (requestCode) { 121 | case PERMISSION_COARSE_LOCATION: 122 | if(grantResults.length < 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED){ 123 | finish(); 124 | } 125 | break; 126 | } 127 | } 128 | 129 | private void setEnabled(boolean enabled){ 130 | mPurchaseBtn.setEnabled(enabled); 131 | mRefundBtn.setEnabled(enabled); 132 | mDeactivateBtn.setEnabled(enabled); 133 | mActivateBtn.setEnabled(enabled); 134 | mUpdateBtn.setEnabled(enabled); 135 | mReprintBtn.setEnabled(enabled); 136 | mPrintBtn.setEnabled(enabled); 137 | } 138 | 139 | private void setConnectionListener(){ 140 | mPOSHandler.setConnectionListener(new ConnectionListener() { 141 | @Override 142 | public void onConnected(final BluetoothDevice device) { 143 | runOnUiThread(new Runnable() { 144 | @Override 145 | public void run() { 146 | mStatus.setText("Connected"); 147 | 148 | mTerminalType.setVisibility(View.VISIBLE); 149 | 150 | if( device == null ) 151 | mTerminalType.setText("E500"); 152 | else 153 | mTerminalType.setText(device.getName().equalsIgnoreCase("") ? device.getAddress() : device.getName()); 154 | 155 | setEnabled(true); 156 | } 157 | }); 158 | } 159 | }); 160 | } 161 | 162 | private void setPosInfoListener(){ 163 | mPOSHandler.setPOSInfoListener(new POSInfoListener() { 164 | @Override 165 | public void onPOSInfoReceived(final int command, final int status, final String description, Bundle extra) { 166 | // handle pos info events here 167 | } 168 | 169 | @Override 170 | public void onTransactionComplete(final TransactionData transactionData) { 171 | // handle purchase and refund transactions complete here 172 | } 173 | }); 174 | } 175 | 176 | @Override 177 | public void onClick(View view) { 178 | if( view.getId() == mConnectBtn.getId() ){ 179 | POSHandler.getInstance().connectDevice(this); 180 | return; 181 | } 182 | 183 | if( !POSHandler.getInstance().isConnected()){ 184 | mToast.setText("No terminal connected to this device."); 185 | mToast.show(); 186 | return; 187 | } 188 | if( mTerminalType.getVisibility() != View.VISIBLE ){ 189 | mToast.setText("Terminal is not ready for operations yet. Please wait."); 190 | mToast.show(); 191 | return; 192 | } 193 | 194 | if( view.getId() == mPurchaseBtn.getId() ){ 195 | paymentViaActivity(); 196 | } 197 | else if( view.getId() == mRefundBtn.getId() ){ 198 | refundViaActivity(); 199 | } 200 | else if( view.getId() == mDeactivateBtn.getId() ){ 201 | mPOSHandler.deactivate(); 202 | } 203 | else if( view.getId() == mActivateBtn.getId() ){ 204 | mPOSHandler.activate(); 205 | } 206 | else if( view.getId() == mUpdateBtn.getId() ){ 207 | mPOSHandler.update(); 208 | } 209 | else if( view.getId() == mReprintBtn.getId() ){ 210 | mPOSHandler.reprintReceipt(); 211 | } 212 | else if( view.getId() == mPrintBtn.getId() ){ 213 | ReceiptData receiptData = new ReceiptData(); 214 | receiptData.addLogo(1); 215 | receiptData.addEmptyRow(); 216 | receiptData.addRow("CENTER", ReceiptData.Align.CENTER, ReceiptData.FontSize.SINGLE); 217 | receiptData.addEmptyRow(); 218 | receiptData.addRow("LEFT", ReceiptData.Align.LEFT, ReceiptData.FontSize.SINGLE); 219 | receiptData.addRow("RIGHT", ReceiptData.Align.RIGHT, ReceiptData.FontSize.SINGLE); 220 | receiptData.addEmptyRow(); 221 | receiptData.addRow("LEFT DOUBLE", ReceiptData.Align.LEFT, ReceiptData.FontSize.DOUBLE); 222 | receiptData.addRow("RIGHT DOUBLE", ReceiptData.Align.RIGHT, ReceiptData.FontSize.DOUBLE); 223 | receiptData.addRow("CENTER DOUBLE", ReceiptData.Align.CENTER, ReceiptData.FontSize.DOUBLE); 224 | receiptData.addRow("============================", ReceiptData.Align.CENTER, ReceiptData.FontSize.SINGLE); 225 | receiptData.addRow("============================", ReceiptData.Align.CENTER, ReceiptData.FontSize.SINGLE); 226 | receiptData.addEmptyRow(); 227 | receiptData.addEmptyRow(); 228 | mPOSHandler.printReceipt(receiptData); 229 | } 230 | } 231 | 232 | private void paymentViaActivity(){ 233 | mPOSHandler.openPaymentActivity( 234 | MainActivity.this /*activity*/, 235 | REQUEST_CODE_MAKE_PAYMENT /*requestCode*/, 236 | "" /*amount*/, 237 | UUID.randomUUID().toString()/*transaction reference*/ 238 | ); 239 | } 240 | 241 | private void directPayment(){ 242 | mPOSHandler.purchase( 243 | "10.50" /*amount*/, 244 | UUID.randomUUID().toString()/*transaction reference*/, 245 | POSHandler.RECEIPT_DO_NOT_PRINT /*receipt configuration*/ 246 | ); 247 | } 248 | 249 | private void refundViaActivity(){ 250 | mPOSHandler.openRefundActivity( 251 | MainActivity.this /*activity*/, 252 | REQUEST_CODE_MAKE_REFUND /*requestCode*/, 253 | "" /*amount*/, 254 | UUID.randomUUID().toString()/*transaction reference*/ 255 | ); 256 | } 257 | 258 | private void directRefund(){ 259 | mPOSHandler.refund( 260 | "10.50" /*amount*/, 261 | UUID.randomUUID().toString()/*transaction reference*/, 262 | POSHandler.RECEIPT_DO_NOT_PRINT /*receipt configuration*/ 263 | ); 264 | } 265 | 266 | @Override 267 | protected void onActivityResult(int requestCode, int resultCode, Intent data){ 268 | if( requestCode == REQUEST_CODE_MAKE_PAYMENT && resultCode == RESULT_OK) { 269 | TransactionData transactionData = data.getParcelableExtra(POSHandler.INTENT_EXTRA_TRANSACTION_DATA); 270 | showTransactionDataAlert(transactionData); 271 | // handle transaction data, result of payment via activity 272 | } 273 | else if( requestCode == REQUEST_CODE_MAKE_REFUND && resultCode == RESULT_OK){ 274 | TransactionData transactionData = data.getParcelableExtra(POSHandler.INTENT_EXTRA_TRANSACTION_DATA); 275 | // handle transaction data, result of refund via activity 276 | } 277 | } 278 | 279 | private void showTransactionDataAlert(TransactionData transactionData){ 280 | String message = "Auth code: " + transactionData.getAuthCode() + "\n"; 281 | message += "Approval: " + transactionData.getApproval() + "\n"; 282 | message += "Transaction Local Date: " + transactionData.getTransactionDateLocal() + "\n"; 283 | message += "RRN: " + transactionData.getRRN() + "\n"; 284 | message += "Amount: " + transactionData.getAmount() + "\n"; 285 | message += "Currency: " + transactionData.getCurrencyIsoCode() + "\n"; 286 | message += "Terminal ID: " + transactionData.getTerminalID() + "\n"; 287 | message += "Merchant ID: " + transactionData.getMerchantID() + "\n"; 288 | message += "Merchant Name: " + transactionData.getMerchantName() + "\n"; 289 | message += "Merchant Address Line 1: " + transactionData.getMerchantAddressLine1() + "\n"; 290 | message += "Merchant Address Line 2: " + transactionData.getMerchantAddressLine2() + "\n"; 291 | message += "PAN Masked: " + transactionData.getPANMasked() + "\n"; 292 | message += "Emboss Name: " + transactionData.getEmbossName() + "\n"; 293 | message += "AID: " + transactionData.getAID() + "\n"; 294 | message += "AID Name: " + transactionData.getAIDName() + "\n"; 295 | message += "STAN: " + transactionData.getStan() + "\n"; 296 | message += "Is Signature Required: " + transactionData.isSignatureRequired(); 297 | 298 | 299 | final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this); 300 | alertBuilder.setTitle("Transaction data"); 301 | alertBuilder.setPositiveButton("OK", null); 302 | alertBuilder.setMessage(message); 303 | 304 | runOnUiThread(new Runnable() { 305 | @Override 306 | public void run() { 307 | AlertDialog alertDialog = alertBuilder.create(); 308 | alertDialog.show(); 309 | } 310 | }); 311 | } 312 | 313 | private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 314 | public void onReceive(Context context, Intent intent) { 315 | if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction())) { 316 | BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 317 | 318 | if( POSHandler.getInstance().getConnectedDevice() != null && device != null && 319 | POSHandler.getInstance().getConnectedDevice().getAddress().equalsIgnoreCase(device.getAddress())){ 320 | 321 | mStatus.setText("Not connected"); 322 | mTerminalType.setText(""); 323 | mTerminalType.setVisibility(View.INVISIBLE); 324 | setEnabled(false); 325 | } 326 | } 327 | } 328 | }; 329 | } 330 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_shape_clicked.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_shape_disabled.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/white_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developermypos/myPOS-SDK-Android/ec93365c1b43962a75f79ab0e00aeb944a365e9e/app/src/main/res/drawable/white_background.9.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 24 | 25 | 35 | 36 | 47 | 48 |