├── .travis.yml ├── LICENSE ├── README.md ├── accept-sdk-android-acceptsdksource-release.aar ├── build.gradle ├── demo ├── AcceptSDKAndroidDemo.properties ├── demo │ ├── .gitignore │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── sample │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── de │ │ │ │ └── wirecard │ │ │ │ └── accept │ │ │ │ └── sample │ │ │ │ ├── ApplicationTest.java │ │ │ │ └── SdkTest.java │ │ │ ├── androidTestFlavor_bbpos │ │ │ └── java │ │ │ │ └── de │ │ │ │ └── wirecard │ │ │ │ └── accept │ │ │ │ └── sample │ │ │ │ └── BbposTest.java │ │ │ ├── androidTestFlavor_thyron │ │ │ └── java │ │ │ │ └── de │ │ │ │ └── wirecard │ │ │ │ └── accept │ │ │ │ └── sample │ │ │ │ └── ThyronTest.java │ │ │ ├── flavor_bbpos │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── de │ │ │ │ │ └── wirecard │ │ │ │ │ └── accept │ │ │ │ │ └── sample │ │ │ │ │ ├── MenuActivity.java │ │ │ │ │ └── PaymentFlowActivity.java │ │ │ └── res │ │ │ │ └── values │ │ │ │ ├── config_for_accept.xml │ │ │ │ └── strings.xml │ │ │ ├── flavor_thyron │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── de │ │ │ │ │ └── wirecard │ │ │ │ │ └── accept │ │ │ │ │ └── sample │ │ │ │ │ ├── AbstractSpireMenuActivity.java │ │ │ │ │ ├── ConfigurationAndFirmwareUpdateActivity.java │ │ │ │ │ ├── MenuActivity.java │ │ │ │ │ └── PaymentFlowActivity.java │ │ │ └── res │ │ │ │ ├── layout │ │ │ │ ├── activity_firmware_update.xml │ │ │ │ └── activity_menu.xml │ │ │ │ └── values │ │ │ │ ├── config_for_accept.xml │ │ │ │ └── strings.xml │ │ │ ├── flavor_thyronUsb │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── de │ │ │ │ │ └── wirecard │ │ │ │ │ └── accept │ │ │ │ │ └── sample │ │ │ │ │ ├── AbstractSpireMenuActivity.java │ │ │ │ │ ├── ConfigurationAndFirmwareUpdateActivity.java │ │ │ │ │ ├── MenuActivity.java │ │ │ │ │ └── PaymentFlowActivity.java │ │ │ └── res │ │ │ │ ├── layout │ │ │ │ ├── activity_firmware_update.xml │ │ │ │ └── activity_menu.xml │ │ │ │ └── values │ │ │ │ ├── config_for_accept.xml │ │ │ │ └── strings.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── de │ │ │ │ └── wirecard │ │ │ │ └── accept │ │ │ │ └── sample │ │ │ │ ├── AbstractCardPaymentFlowActivity.java │ │ │ │ ├── AbstractMenuActivity.java │ │ │ │ ├── AbstractPaymentFlowActivity.java │ │ │ │ ├── AdditionalPaymentFieldsActivity.java │ │ │ │ ├── AlipayPaymentActivity.java │ │ │ │ ├── Application.java │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── CashPaymentActivity.java │ │ │ │ ├── CurrencyUtils.java │ │ │ │ ├── LoginActivity.java │ │ │ │ ├── PaymentFlowDialogs.java │ │ │ │ ├── PaymentFlowSignatureView.java │ │ │ │ ├── Receipt.java │ │ │ │ ├── SubMerchantInfoActivity.java │ │ │ │ ├── TransactionsHistoryActivity.java │ │ │ │ └── WrongAcceptSettingsActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ ├── activity_additional_payment_fields.xml │ │ │ ├── activity_firmware_update.xml │ │ │ ├── activity_history.xml │ │ │ ├── activity_login.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_menu.xml │ │ │ ├── activity_payment.xml │ │ │ ├── activity_sub_merchant_info.xml │ │ │ ├── activity_wrong.xml │ │ │ ├── dialog_for_sign_confirm.xml │ │ │ ├── dialog_receipt.xml │ │ │ └── row_payment_history.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── config_for_accept.xml │ │ │ ├── strings.xml │ │ │ ├── style.xml │ │ │ └── styles.xml │ └── settings.gradle ├── demo_help_graphics │ ├── AcceptThyronPaymentFlowController.jpg │ ├── bbpos_fullActivityHierarchy.jpg │ └── spire_fullActivityHierarchy.jpg └── flavor_thyronRelease-1.14.6.apk └── docs └── AcceptSDK_Android - Quick Start Guide.pdf /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | jdk: 3 | - oraclejdk8 4 | android: 5 | components: 6 | - tools 7 | - platform-tools 8 | - build-tools-27.0.3 9 | - android-26 10 | - extra-android-m2repository 11 | 12 | before_script: 13 | - cd demo/demo 14 | 15 | script: 16 | - ./gradlew build --stacktrace 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 mposSVK 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # accept-sdk-android 2 | 3 | acceptSDK 4 | 5 | [![CI Status](http://img.shields.io/travis/WirecardMobileServices/acceptSDK-Android.svg)](https://travis-ci.org/WirecardMobileServices/acceptSDK-Android) 6 | [![Version](https://jitpack.io/v/mposSVK/acceptSDK-Android.svg)](https://jitpack.io/#mposSVK/acceptSDK-Android) 7 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) 8 | [![Platform: Android](https://img.shields.io/badge/platform-Android-green.svg)](https://img.shields.io/badge/platform-Android-green.svg) 9 | 10 | ## Overview 11 | The library enables cashless payment processing with selected mPOS terminals (magStripe and Chip and PIN) via the fully-licensed Wirecard Bank, Wirecard Retail Services which allows acceptance of many different cards, including Visa, MasterCard and American Express. 12 | 13 | Check out the applications using the **acceptSDK** and created as **re-branding** of **Wirecard Whitelabel solution** 14 | 15 | accept GER|Lexware pay|accept SGP|M1 mPOS| 16 | -------|-----------|-------|------| 17 | [Accept GER](https://play.google.com/store/apps/details?id=de.wirecard.accept.de "Accept GER")|[Lexware pay](https://play.google.com/store/apps/details?id=de.wirecard.accept.lexware "Lexware pay")|[Accept SGP](https://play.google.com/store/apps/details?id=de.wirecard.accept.sgp "Accept SGP")|[M1 mPOS](https://play.google.com/store/apps/details?id=de.wirecard.accept.m1 "M1 mPOS")| 18 | ## Whitelabel solution 19 | Wirecard Technologies is using the acceptSDK in their Whitelabel application which is fully integrated professional mPOS solution. The Whitelabel app is VISA and Mastercard certified and utilises the Wirecard infrastructure for card payment processing. 20 | 21 | ## Installation 22 | There are two ways how to install the SDK. 23 | 24 | 1. Clone from GitHub and integrate the library to your project as per accept SDK - Quick Start Guide. 25 | 2. acceptSDK is available through gradle dependency 26 | ``` 27 | repositories { 28 | maven { url "https://jitpack.io" } 29 | } 30 | 31 | dependencies { 32 | compile 'com.github.WirecardMobileServices:acceptSDK-Android:1.6.5' 33 | } 34 | ``` 35 | 36 | ## Extension compatibility table 37 | SDK|Spire extension|BBPos extension| 38 | --------|--------|--------| 39 | 1.4.10|1.4.10|1.4.10| 40 | 1.5.4|1.5.3|1.5.1| 41 | 1.5.6.3|1.5.4.1|1.5.1| 42 | 1.5.7|1.5.5|1.5.2| 43 | 1.5.9|1.5.8|1.5.3| 44 | 1.5.10.2|1.5.9.2|1.5.4| 45 | 1.6.0|1.6.0|1.6.0| 46 | 1.6.1|1.6.0|1.6.1| 47 | 1.6.1|1.6.1|1.6.1| 48 | 1.6.2|1.6.2|1.6.2| 49 | 1.6.3|1.6.2|1.6.2| 50 | 1.6.4|1.6.3|1.6.3| 51 | 1.6.5|1.6.3|1.6.3| 52 | 53 | ## Contact 54 | Get in touch with [acceptSDK development team](mailto://mpos-svk@wirecard.com "acceptSDK") for acceptSDK support and mPOS Whitelabel solution 55 | 56 | Get in touch with [Wirecard mPOS retail team](mailto://retail.mpos@wirecard.com "mpos Retails") for Wirecard payment processing services 57 | 58 | ## Documentation 59 | 60 | All the necessary documents are available in the ./docs subfolder. 61 | 62 | Refer to "Android Accept SDK - Quick Start Guide.pdf" for the details on how to use acceptSDK. 63 | 64 | If using accepdSDK pod the all the required libraries are taken care of by the gradle. 65 | 66 | ## Requirements 67 | * Device running Android > 3.0 68 | * One of Wirecard approved terminals and handheld printers 69 | * BBPOS [uEMV Swiper - Chipper](http://bbpos.com/en/solutions/hardware/ "Chipper") 70 | * Spire [PosMate](http://www.spirepayments.com/product/posmate/ "PosMate") 71 | * Spire [SPm2](http://www.spirepayments.com/product/spm2/ "SPm2") 72 | * Datecs printer [DPP-250](http://www.datecs.bg/en/products/61 "DPP-250") 73 | 74 | ## Authors 75 | 76 | Wirecard Technologies Slovakia, mpos-svk@wirecard.com 77 | 78 | -------------------------------------------------------------------------------- /accept-sdk-android-acceptsdksource-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WirecardMobileServices/acceptSDK-Android/57c525d25661b152e2d1c33c61c08a651697dcbb/accept-sdk-android-acceptsdksource-release.aar -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven' 2 | 3 | group='com.github.mposSVK' 4 | version='release' 5 | 6 | artifacts { 7 | archives new File('accept-sdk-android-acceptsdksource-release.aar') 8 | } 9 | 10 | uploadArchives { 11 | repositories { 12 | mavenDeployer { 13 | repository(url: mavenLocal().url) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /demo/AcceptSDKAndroidDemo.properties: -------------------------------------------------------------------------------- 1 | #Place this file above the project structure. NOT inside. 2 | 3 | clientID="d2fee3aa586b4b7062315742d29456effaf80636dfb89febcdc19f1bb4ff6111" 4 | clientSecret="d29aab08958d6f8ab59c2e3a3348b41b0861823784b2d456b2ba9769464b6111" 5 | apiPath="https://sdk-integration.dev.up-next.io/" 6 | -------------------------------------------------------------------------------- /demo/demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle files 2 | .gradle/ 3 | build/ 4 | 5 | # Local configuration file (sdk path, etc) 6 | local.properties 7 | 8 | # Intellij 9 | *.iml 10 | .idea 11 | 12 | sample/libs/ 13 | /sample/proguard-rules.pro 14 | #.gitignore 15 | -------------------------------------------------------------------------------- /demo/demo/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | mavenCentral() 7 | maven { url "https://maven.google.com" } 8 | google() 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.1.4' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | 19 | repositories { 20 | google() 21 | } -------------------------------------------------------------------------------- /demo/demo/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | #org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | 19 | org.gradle.parallel=true 20 | org.gradle.jvmargs=-Xmx1536M -------------------------------------------------------------------------------- /demo/demo/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WirecardMobileServices/acceptSDK-Android/57c525d25661b152e2d1c33c61c08a651697dcbb/demo/demo/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /demo/demo/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 12 15:07:03 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /demo/demo/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /demo/demo/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /demo/demo/sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | repositories { 4 | jcenter() 5 | maven { url "https://maven.google.com" } 6 | maven { url "https://jitpack.io" } 7 | flatDir { 8 | dirs 'libs' 9 | } 10 | } 11 | 12 | android { 13 | compileSdkVersion 26 14 | buildToolsVersion '27.0.3' 15 | defaultConfig { 16 | applicationId "de.wirecard.accept.sample" 17 | minSdkVersion 16 18 | targetSdkVersion 26 19 | versionCode 19 20 | versionName "1.14.6" 21 | } 22 | packagingOptions { 23 | exclude 'META-INF/DEPENDENCIES' 24 | exclude 'META-INF/notice.txt' 25 | exclude 'META-INF/license.txt' 26 | exclude 'META-INF/LICENSE' 27 | exclude 'META-INF/LICENSE.txt' 28 | exclude 'META-INF/NOTICE' 29 | exclude 'META-INF/NOTICE.txt' 30 | exclude 'META-INF/services/com.fasterxml.jackson.core.JsonFactory' 31 | 32 | } 33 | 34 | useLibrary 'org.apache.http.legacy' 35 | flavorDimensions "terminal" 36 | 37 | productFlavors { 38 | flavor_thyron { 39 | applicationId 'de.wirecard.accept.sample.thyron' 40 | dimension "terminal" 41 | } 42 | 43 | flavor_thyronUsb { 44 | applicationId 'de.wirecard.accept.sample.usb' 45 | dimension "terminal" 46 | } 47 | 48 | flavor_bbpos { 49 | applicationId 'de.wirecard.accept.sample.bbpos' 50 | dimension "terminal" 51 | } 52 | } 53 | 54 | buildTypes { 55 | release { 56 | minifyEnabled true 57 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 58 | } 59 | all { 60 | def Properties appProps = new Properties() 61 | try { 62 | appProps.load(new FileInputStream(file("../../AcceptSDKAndroidDemo.properties"))) 63 | } catch (IOException e) { 64 | appProps.put("clientID", System.getenv('BACKEND_DEFAULT_UID')) 65 | appProps.put("clientSecret", System.getenv('BACKEND_DEFAULT_SECRET')) 66 | appProps.put("apiPath", System.getenv('BACKEND_DEFAULT_URL')) 67 | } 68 | 69 | buildConfigField "String", "clientID", appProps.getProperty("clientID", "\"\"") 70 | buildConfigField "String", "clientSecret", appProps.getProperty("clientSecret", "\"\"") 71 | buildConfigField "String", "apiPath", appProps.getProperty("apiPath", "\"\"") 72 | 73 | } 74 | } 75 | 76 | applicationVariants.all { variant -> 77 | variant.outputs.all { 78 | outputFileName = "${variant.name}-${variant.versionName}.apk" 79 | } 80 | } 81 | 82 | } 83 | 84 | dependencies { 85 | implementation 'com.github.WirecardMobileServices:acceptSDK-Android:1.6.5' 86 | flavor_bbposImplementation 'com.github.WirecardMobileServices:accept-android-extension-bbpos:1.6.3' 87 | flavor_thyronImplementation 'com.github.WirecardMobileServices:accept-android-extension-spire:1.6.3' 88 | flavor_thyronUsbImplementation 'com.github.WirecardMobileServices:accept-android-extension-spire:1.6.3' 89 | 90 | implementation 'com.android.support:appcompat-v7:26.0.2' 91 | implementation 'com.android.support:design:26.0.2' 92 | implementation 'com.squareup.picasso:picasso:2.5.2' 93 | implementation 'com.journeyapps:zxing-android-embedded:3.5.0' 94 | implementation 'com.scottyab:rootbeer-lib:0.0.6' 95 | } 96 | -------------------------------------------------------------------------------- /demo/demo/sample/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:\Users\marek.richter\AppData\Local\Android\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 | -------------------------------------------------------------------------------- /demo/demo/sample/src/androidTest/java/de/wirecard/accept/sample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /demo/demo/sample/src/androidTest/java/de/wirecard/accept/sample/SdkTest.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.test.AndroidTestCase; 4 | 5 | import de.wirecard.accept.sdk.AcceptSDK; 6 | 7 | public class SdkTest extends AndroidTestCase { 8 | 9 | public void testSdkExtensions() throws Exception { 10 | System.out.println("testSdkExtensions()"); 11 | System.out.println("SDK version: " + AcceptSDK.getSDKVersion()); 12 | 13 | } 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /demo/demo/sample/src/androidTestFlavor_bbpos/java/de/wirecard/accept/sample/BbposTest.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.test.AndroidTestCase; 4 | 5 | import de.wirecard.accept.extension.bbpos.BuildConfig; 6 | 7 | public class BbposTest extends AndroidTestCase { 8 | 9 | public void testBbposExtension() throws Exception { 10 | System.out.println("testBbposExtension()"); 11 | 12 | System.out.println("Bbpos Bbpod extension flavor: " + BuildConfig.FLAVOR); 13 | 14 | System.out.println("Bbpos version code: " + BuildConfig.VERSION_CODE); 15 | System.out.println("Bbpos version name: " + BuildConfig.VERSION_NAME); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /demo/demo/sample/src/androidTestFlavor_thyron/java/de/wirecard/accept/sample/ThyronTest.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.test.AndroidTestCase; 4 | 5 | import de.wirecard.accept.extension.SpireExtension; 6 | import de.wirecard.accept.extension.thyron.BuildConfig; 7 | 8 | public class ThyronTest extends AndroidTestCase { 9 | 10 | public void testTyronExtension() throws Exception { 11 | System.out.println("testTyronExtension()"); 12 | 13 | System.out.println("Thyron ThyronExtension.THYRON_NAME: " + SpireExtension.SPIRE_NAME); 14 | 15 | System.out.println("Thyron version code: " + BuildConfig.VERSION_CODE); 16 | System.out.println("Thyron version name: " + BuildConfig.VERSION_NAME); 17 | 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_bbpos/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_bbpos/java/de/wirecard/accept/sample/MenuActivity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Wirecard. All rights reserved. 3 | * 4 | * Accept SDK for Android 5 | * 6 | */ 7 | package de.wirecard.accept.sample; 8 | 9 | import android.Manifest; 10 | import android.content.pm.PackageManager; 11 | import android.os.Build; 12 | import android.os.Bundle; 13 | import android.support.annotation.NonNull; 14 | import android.support.v4.app.ActivityCompat; 15 | import android.view.View; 16 | import android.widget.Button; 17 | import android.widget.Toast; 18 | 19 | import java.util.List; 20 | 21 | import de.wirecard.accept.extension.AcceptBbposPaymentFlowController; 22 | import de.wirecard.accept.sdk.extensions.Device; 23 | import de.wirecard.accept.sdk.extensions.PaymentFlowController; 24 | 25 | public class MenuActivity extends AbstractMenuActivity { 26 | 27 | protected int RECORD_RESPONSE_CODE = 110; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | 33 | Button discoverDevicesButton = (Button) findViewById(R.id.discoverDevices); 34 | if (discoverDevicesButton != null) { 35 | discoverDevicesButton.setOnClickListener(new View.OnClickListener() { 36 | @Override 37 | public void onClick(View v) { 38 | currentUsedDevice = null; //because we will not use remembered one 39 | if (!checkRecordPermitionOrStart()) 40 | discoverDevices(); 41 | } 42 | }); 43 | } 44 | 45 | if (currentUsedDevice == null) 46 | if (!checkRecordPermitionOrStart()) 47 | discoverDevices();// >>> Follow here to step 1. <<< 48 | } 49 | 50 | private boolean checkRecordPermitionOrStart() { 51 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 52 | if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED 53 | || ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.MODIFY_AUDIO_SETTINGS) != PackageManager.PERMISSION_GRANTED 54 | //|| ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED 55 | ) { 56 | requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.BLUETOOTH}, RECORD_RESPONSE_CODE); 57 | return true; 58 | } 59 | } 60 | return false; 61 | } 62 | 63 | @Override 64 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 65 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 66 | if (requestCode == RECORD_RESPONSE_CODE 67 | && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED 68 | && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.MODIFY_AUDIO_SETTINGS) == PackageManager.PERMISSION_GRANTED 69 | //&& ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED 70 | ) { 71 | discoverDevices(); 72 | } 73 | else { 74 | Toast.makeText(getApplicationContext(), "Permission problem", Toast.LENGTH_LONG).show(); 75 | } 76 | } 77 | 78 | void discoverDevices() { 79 | //>>>>>>>>>> 1. create controller instance 80 | final AcceptBbposPaymentFlowController controller = new AcceptBbposPaymentFlowController(this); 81 | 82 | //>>>>>>>>>> 2. call discovery devices 83 | //like first we have to call discover devices to get list of paired device from smartphone 84 | controller.discoverDevices(getApplicationContext(), new PaymentFlowController.BBPosDiscoverDelegate() { 85 | @Override 86 | public void onDiscoveryError(PaymentFlowController.DiscoveryError discoveryError, String s) { 87 | //Check DiscoveryError enum states for translations 88 | Toast.makeText(getApplicationContext(), "Check terminal: " + discoveryError.name(), Toast.LENGTH_LONG).show(); 89 | } 90 | 91 | @Override 92 | public void onDiscoveredDevices(List list) { 93 | //received all paired devices from smart phone 94 | if (list == null || list.isEmpty()) { 95 | Toast.makeText(getApplicationContext(), "Settings: list of connected devices empty, please insert terminal before.", Toast.LENGTH_LONG).show(); 96 | return; 97 | } 98 | // just one device because using audio jack 99 | currentUsedDevice = list.get(0); 100 | Toast.makeText(getApplicationContext(), "One device connected: " + currentUsedDevice.displayName, Toast.LENGTH_LONG).show(); 101 | } 102 | }); 103 | 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_bbpos/java/de/wirecard/accept/sample/PaymentFlowActivity.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.Manifest; 4 | import android.content.pm.PackageManager; 5 | import android.os.Build; 6 | import android.support.annotation.NonNull; 7 | import android.support.v4.app.ActivityCompat; 8 | import android.text.TextUtils; 9 | import android.view.View; 10 | import android.widget.Toast; 11 | 12 | import java.util.List; 13 | 14 | import de.wirecard.accept.extension.AcceptBbposPaymentFlowController; 15 | import de.wirecard.accept.sdk.L; 16 | import de.wirecard.accept.sdk.extensions.Device; 17 | import de.wirecard.accept.sdk.extensions.PaymentFlowController; 18 | 19 | public class PaymentFlowActivity extends AbstractCardPaymentFlowActivity { 20 | 21 | 22 | protected int RECORD_RESPONSE_CODE = 111; 23 | 24 | @Override 25 | PaymentFlowController createNewController() { 26 | return new AcceptBbposPaymentFlowController(this); 27 | } 28 | 29 | @Override 30 | boolean isSignatureConfirmationInApplication() { 31 | return true; 32 | } 33 | 34 | boolean isRequiredPermissionOnStart() { 35 | return checkRecordPermitionOrStart(); 36 | } 37 | 38 | private boolean checkRecordPermitionOrStart() { 39 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 40 | if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED 41 | || ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.MODIFY_AUDIO_SETTINGS) != PackageManager.PERMISSION_GRANTED 42 | //|| ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED 43 | ) { 44 | requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.BLUETOOTH}, RECORD_RESPONSE_CODE); 45 | return true; 46 | } 47 | } 48 | return false; 49 | } 50 | 51 | @Override 52 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 53 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 54 | if (requestCode == RECORD_RESPONSE_CODE 55 | && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED 56 | && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.MODIFY_AUDIO_SETTINGS) == PackageManager.PERMISSION_GRANTED 57 | //&& ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED 58 | ) { 59 | proceedToDevicesDiscovery(); 60 | } 61 | else { 62 | Toast.makeText(getApplicationContext(), "Permission problem", Toast.LENGTH_LONG).show(); 63 | } 64 | } 65 | 66 | @Override 67 | void startPaymentFlow(Device device, long amount) throws IllegalStateException { 68 | paymentFlowController.startPaymentFlow(device, amount, getAmountCurrency(), this); 69 | } 70 | 71 | 72 | @Override 73 | PaymentFlowController.DiscoverDelegate getDiscoverDelegate() { 74 | return new PaymentFlowController.BBPosDiscoverDelegate() { 75 | 76 | @Override 77 | public void onDiscoveryError(final PaymentFlowController.DiscoveryError error, final String technicalMessage) { 78 | L.e(TAG, ">>> onDiscoveryError"); 79 | runOnUiThreadIfNotDestroyed(new Runnable() { 80 | @Override 81 | public void run() { 82 | showProgress(-1, false); 83 | PaymentFlowDialogs.showTerminalDiscoveryError(PaymentFlowActivity.this, error, technicalMessage, new View.OnClickListener() { 84 | @Override 85 | public void onClick(View v) { 86 | //finish(); 87 | } 88 | }); 89 | } 90 | }); 91 | } 92 | 93 | @Override 94 | public void onDiscoveredDevices(final List devices) { 95 | L.e(TAG, ">>> onDiscoveredDevices"); 96 | runOnUiThreadIfNotDestroyed(new Runnable() { 97 | @Override 98 | public void run() { 99 | showProgress(-1, false); 100 | if (devices.isEmpty()) { 101 | PaymentFlowDialogs.showNoDevicesError(PaymentFlowActivity.this, new View.OnClickListener() { 102 | @Override 103 | public void onClick(View v) { 104 | //finish(); 105 | } 106 | }); 107 | return; 108 | } 109 | if (devices.size() == 1) { 110 | currentDevice = devices.get(0); 111 | return; 112 | } 113 | PaymentFlowDialogs.showTerminalChooser(PaymentFlowActivity.this, devices, new PaymentFlowDialogs.DeviceToStringConverter() { 114 | @Override 115 | public String displayNameForDevice(Device device) { 116 | if (TextUtils.isEmpty(device.displayName)) { 117 | return device.id; 118 | } 119 | return device.displayName; 120 | } 121 | }, new PaymentFlowDialogs.TerminalChooserListener() { 122 | @Override 123 | public void onDeviceSelected(Device device) { 124 | currentDevice = device; 125 | } 126 | 127 | @Override 128 | public void onSelectionCanceled() { 129 | finish(); 130 | } 131 | }); 132 | } 133 | }); 134 | } 135 | }; 136 | } 137 | 138 | 139 | } 140 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_bbpos/res/values/config_for_accept.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BBPosExtension 5 | 6 | 7 | 8 | BBPosExtension 9 | 10 | 11 | false 12 | false 13 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_bbpos/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Accept Sample App - bbpos 5 | 6 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_thyron/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_thyron/java/de/wirecard/accept/sample/AbstractSpireMenuActivity.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.os.Bundle; 8 | import android.support.v7.app.AlertDialog; 9 | import android.text.TextUtils; 10 | import android.view.View; 11 | import android.widget.Button; 12 | import android.widget.Toast; 13 | 14 | import java.util.List; 15 | 16 | import de.wirecard.accept.extension.refactor.FirmwareVersionCheckAsyncTask; 17 | import de.wirecard.accept.sdk.AcceptSDK; 18 | import de.wirecard.accept.sdk.extensions.Device; 19 | import de.wirecard.accept.sdk.extensions.PaymentFlowController; 20 | 21 | public abstract class AbstractSpireMenuActivity extends AbstractMenuActivity { 22 | 23 | private static final int REQUEST_CONFIG_OR_FIRMWARE_UPDATE_ACTIVITY = 11; 24 | private ProgressDialog progressDialog; 25 | 26 | private final String rupayCAP = "Rupay Cash at POS"; 27 | private final String masterAndVisaPWCB = "Master/Visa purchase with cashback"; 28 | private final String[] menu = new String[]{rupayCAP, masterAndVisaPWCB}; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | 34 | findViewById(R.id.payment).setOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | Intent i = PaymentFlowActivity.intent(getApplicationContext()); 38 | i.putExtra(BaseActivity.CURRENT_DEVICE, currentUsedDevice); 39 | startActivity(i); 40 | } 41 | }); 42 | 43 | findViewById(R.id.sepa).setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | Intent i = PaymentFlowActivity.intent(getApplicationContext()); 47 | i.putExtra(BaseActivity.SEPA, true); 48 | startActivity(i); 49 | } 50 | }); 51 | 52 | findViewById(R.id.cash_payment).setOnClickListener(new View.OnClickListener() { 53 | @Override 54 | public void onClick(View v) { 55 | startActivity(CashPaymentActivity.intent(getApplicationContext())); 56 | } 57 | }); 58 | 59 | findViewById(R.id.alipay).setOnClickListener(new View.OnClickListener() { 60 | @Override 61 | public void onClick(View v) { 62 | startActivity(AlipayPaymentActivity.intent(getApplicationContext())); 63 | } 64 | }); 65 | 66 | 67 | Button cashBackButton = (Button) findViewById(R.id.cash_back_payment); 68 | if (cashBackButton != null) { 69 | cashBackButton.setOnClickListener(new View.OnClickListener() { 70 | @Override 71 | public void onClick(View v) { 72 | final Intent i = PaymentFlowActivity.intent(getApplicationContext()); 73 | 74 | AlertDialog.Builder builder = new AlertDialog.Builder(AbstractSpireMenuActivity.this); 75 | //just simple way how to display data into the list 76 | builder.setItems(menu, new DialogInterface.OnClickListener() { 77 | @Override 78 | public void onClick(DialogInterface dialog, int which) { 79 | if (menu[which].equals(rupayCAP)) { 80 | i.putExtra(BaseActivity.CASH_BACK, AcceptSDK.CashBack.rupayCashBack.getValue()); 81 | startActivity(i); 82 | } 83 | else if (menu[which].equals(masterAndVisaPWCB)) { 84 | i.putExtra(BaseActivity.CASH_BACK, AcceptSDK.CashBack.masterVisaCashBack.getValue()); 85 | startActivity(i); 86 | } 87 | } 88 | }); 89 | builder.show(); 90 | } 91 | }); 92 | } 93 | //additional feature only for Spire(thyron) terminals 94 | Button configUpdateButton = (Button) findViewById(R.id.configUpdate); 95 | if (configUpdateButton != null) 96 | configUpdateButton.setOnClickListener(new View.OnClickListener() { 97 | @Override 98 | public void onClick(View v) { 99 | if(currentUsedDevice == null) { 100 | Toast.makeText(getApplicationContext(), "Device not found > discover devices", Toast.LENGTH_LONG).show(); 101 | return; 102 | } 103 | //device config update 104 | showFirmwareAndConfigActivity(false);// >>> Follow here to step 3. <<< 105 | 106 | } 107 | }); 108 | 109 | //additional feature only for Spire(thyron) terminals 110 | Button firmwareUpdateButton = (Button) findViewById(R.id.firmwareUpdate); 111 | if (firmwareUpdateButton != null) 112 | firmwareUpdateButton.setOnClickListener(new View.OnClickListener() { 113 | @Override 114 | public void onClick(View v) { 115 | if(currentUsedDevice == null) { 116 | Toast.makeText(getApplicationContext(), "Device not found > discover devices", Toast.LENGTH_LONG).show(); 117 | return; 118 | } 119 | //firmware update 120 | showFirmwareAndConfigActivity(true);// >>> Follow here to step 3. <<< 121 | } 122 | }); 123 | 124 | //additional feature only for Spire(thyron) terminals 125 | Button discoverDevicesButton = (Button) findViewById(R.id.discoverDevices); 126 | if (discoverDevicesButton != null) { 127 | discoverDevicesButton.setOnClickListener(new View.OnClickListener() { 128 | @Override 129 | public void onClick(View v) { 130 | currentUsedDevice = null; //because we will not use remembered one 131 | discoverDevices(); 132 | } 133 | }); 134 | } 135 | 136 | if (currentUsedDevice == null) 137 | discoverDevices();// >>> Follow here to step 1. <<< 138 | } 139 | 140 | protected void showSpireBoundedDevicesChooserDialog(Context context, List list, final PaymentFlowController.SelectDeviceDelegate selectDeviceDelegate) { 141 | //this is "currentUsedDevice" selector... goal is to choose one device as "currentUsedDevice" 142 | PaymentFlowDialogs.showTerminalChooser(context, list, 143 | new PaymentFlowDialogs.DeviceToStringConverter() { 144 | @Override 145 | public String displayNameForDevice(Device device) { 146 | if (TextUtils.isEmpty(device.displayName)) { 147 | return device.id; 148 | } 149 | return device.displayName; 150 | } 151 | }, 152 | new PaymentFlowDialogs.TerminalChooserListener() { 153 | @Override 154 | public void onDeviceSelected(Device selectedDevice) { 155 | currentUsedDevice = selectedDevice; 156 | selectDeviceDelegate.onDeviceSelected(currentUsedDevice); 157 | } 158 | 159 | @Override 160 | public void onSelectionCanceled() { 161 | logOut(); 162 | } 163 | }); 164 | } 165 | 166 | /** 167 | * in case of Firmware update fist check availability 168 | * then start ConfigurationAndFirmwareUpdateActivity which is responsible to do connectAnc 169 | * @param firmware True if needed firmware update 170 | */ 171 | protected void showFirmwareAndConfigActivity(boolean firmware) { 172 | if (firmware) { 173 | //in case of firmware we have to check if new version is available first(this will update SDK status) 174 | // Toast.makeText(getApplicationContext(), "Started firmware version check assync task", Toast.LENGTH_LONG).show(); 175 | showFwUpdateCheck(); 176 | new FirmwareVersionCheckAsyncTask(currentUsedDevice, new PaymentFlowController.FirmwareUpdateListener() { 177 | @Override 178 | public void onFirmwareUpdateAvailable() { 179 | //>>>>>>>>>> 3. call controller.connectAndConfigure();... this is done inside ConfigurationAndFirmwareUpdateActivity 180 | //in case its available, lets display activity which will handle update completely (using connectAndConfigure()), 181 | // with terminal communication and data uploading 182 | hideFwUpdateCheck(); 183 | startActivityForResult( 184 | ConfigurationAndFirmwareUpdateActivity.intent(getApplicationContext()) 185 | .putExtra(ConfigurationAndFirmwareUpdateActivity.EXTRA_SELECTED_DEVICE, currentUsedDevice) 186 | .putExtra(ConfigurationAndFirmwareUpdateActivity.EXTRA_ITS_FIRMWARE_UPDATE_ALOWED, true) // true > its firmware 187 | , REQUEST_CONFIG_OR_FIRMWARE_UPDATE_ACTIVITY); 188 | } 189 | 190 | @Override 191 | public void onFirmwareUpdateNotNeeded() { 192 | hideFwUpdateCheck(); 193 | Toast.makeText(getApplicationContext(), "Firmware version on terminal not need to be updated", Toast.LENGTH_LONG).show(); 194 | } 195 | 196 | @Override 197 | public void onConfigureError(PaymentFlowController.Error error, String errorDetails) { 198 | hideFwUpdateCheck(); 199 | Toast.makeText(getApplicationContext(), error.name() + "\n " + errorDetails, Toast.LENGTH_LONG).show(); 200 | } 201 | }).execute(); 202 | } 203 | else { 204 | //>>>>>>>>>> 3. call controller.connectAndConfigure();... this is done in ConfigurationAndFirmwareUpdateActivity 205 | //in case of device config update everything is ready, just start activity and start terminal communication 206 | startActivityForResult( 207 | ConfigurationAndFirmwareUpdateActivity.intent(getApplicationContext()) 208 | .putExtra(ConfigurationAndFirmwareUpdateActivity.EXTRA_SELECTED_DEVICE, currentUsedDevice) 209 | .putExtra(ConfigurationAndFirmwareUpdateActivity.EXTRA_ITS_FIRMWARE_UPDATE_ALOWED, false) 210 | , REQUEST_CONFIG_OR_FIRMWARE_UPDATE_ACTIVITY); 211 | } 212 | 213 | //Q1: Why so complicated? 214 | //You are not allowed to make transaction without device config, 215 | // There fore device config will start if during connection to terminal during payment if its not finished yet !!! 216 | 217 | 218 | //Q2: Firmware data request update is having 2 steps 219 | // step no1. FirmwareVersionCheck (FW its bigger file, therefore you will receive in first step only version and url for download) 220 | // step no2. using received URL you SDK can download firmware file physically, parse, and prepare data for next terminal 221 | // connect and during connection if FW data are prepared in SDK ..it will be uploaded automatically >> ConfigurationAndFirmwareUpdateActivity.EXTRA_ITS_FIRMWARE_UPDATE_ALOWED = true 222 | } 223 | 224 | private void showFwUpdateCheck() { 225 | progressDialog = new ProgressDialog(this); 226 | progressDialog.setMessage("Checking availability of firmware update"); 227 | progressDialog.setIndeterminate(true); 228 | progressDialog.setCancelable(false); 229 | progressDialog.show(); 230 | } 231 | 232 | private void hideFwUpdateCheck(){ 233 | if (progressDialog != null){ 234 | progressDialog.dismiss(); 235 | progressDialog = null; 236 | } 237 | } 238 | 239 | @Override 240 | protected void onDestroy() { 241 | super.onDestroy(); 242 | hideFwUpdateCheck(); 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_thyron/java/de/wirecard/accept/sample/ConfigurationAndFirmwareUpdateActivity.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.bluetooth.BluetoothAdapter; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.text.TextUtils; 8 | import android.util.Log; 9 | import android.view.View; 10 | import android.view.WindowManager; 11 | import android.widget.Button; 12 | import android.widget.TextView; 13 | 14 | import de.wirecard.accept.extension.refactor.AcceptThyronPaymentFlowController; 15 | import de.wirecard.accept.sdk.AcceptSDK; 16 | import de.wirecard.accept.sdk.extensions.Device; 17 | import de.wirecard.accept.sdk.extensions.PaymentFlowController; 18 | 19 | /** 20 | * responsible for phisicaly communication with terminal during FW or Device config update 21 | * download files, store it and upload to Spire terminal 22 | * 23 | * Configuration update is just about start communication with terminal, because its automatic (can happend that it will be sterted during your first payment, if not connected yet) 24 | * Firmware update requires two steps. Firmware version check, and AcceptThyronPaymentFlowController.connectAndConfigure()... this is done here in this activity. 25 | */ 26 | public class ConfigurationAndFirmwareUpdateActivity extends BaseActivity implements PaymentFlowController.ConfigureListener { 27 | private static String TAG = ConfigurationAndFirmwareUpdateActivity.class.getSimpleName(); 28 | 29 | public static final String EXTRA_SELECTED_DEVICE = "selected_device"; 30 | public static final String EXTRA_ITS_FIRMWARE_UPDATE_ALOWED = "firmware_update_alowed_mode"; 31 | 32 | TextView message_text; 33 | TextView progress_text; 34 | Button cancelButton; 35 | 36 | private Device currentDev; 37 | private AcceptThyronPaymentFlowController controller = null; //old version of implementation 38 | private boolean firmwareUpdateAlowedMode = true; 39 | private boolean finishedUpdate = false; 40 | 41 | public static Intent intent(final Context context) { 42 | return new Intent(context, ConfigurationAndFirmwareUpdateActivity.class); 43 | } 44 | 45 | 46 | @Override 47 | protected void onCreate(Bundle savedInstanceState) { 48 | super.onCreate(savedInstanceState); 49 | setContentView(R.layout.activity_firmware_update); 50 | configInProgressFileCounter = 0; 51 | message_text = (TextView) findViewById(R.id.textViewMessage); 52 | progress_text = (TextView) findViewById(R.id.textViewProgress); 53 | onConnectionStarted(); 54 | 55 | cancelButton = (Button) findViewById(R.id.button); 56 | cancelButton.setOnClickListener(new View.OnClickListener() { 57 | @Override 58 | public void onClick(View v) { 59 | //result is set 60 | finish(); 61 | } 62 | }); 63 | firmwareUpdateAlowedMode = getIntent().getExtras().getBoolean(ConfigurationAndFirmwareUpdateActivity.EXTRA_ITS_FIRMWARE_UPDATE_ALOWED, true); 64 | 65 | // create default controller using .. new AcceptThyronPaymentFlowController() in case you will not use usb, 66 | // because demo is parametrised here is used full constructor instead 67 | controller = new AcceptThyronPaymentFlowController(true, false, ((Application) getApplicationContext()).usb); 68 | currentDev = getIntent().getExtras().getParcelable(ConfigurationAndFirmwareUpdateActivity.EXTRA_SELECTED_DEVICE); 69 | setResult(RESULT_CANCELED); 70 | } 71 | 72 | @Override 73 | protected void onStart() { 74 | super.onStart(); 75 | //demo app feature ... check if BT is on 76 | boolean usb = ((Application) getApplicationContext()).usb; 77 | if (!usb) { 78 | //check BT first. 79 | BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 80 | if (mBluetoothAdapter == null) { 81 | progress_text.setText("bluetooth_is_currently_powered_off"); 82 | message_text.setText("Enable Bluetooth and try again"); 83 | return; 84 | } 85 | } 86 | 87 | //connectAndConfigure is new, "whole firmware update process wrapping" method, 88 | // using async tasks for download fresh data from backend from remembered url in previous steps(>>> MenuActivity.showFirmwareAndConfigActivity()) 89 | // !!! pls use with firmwareUpdateAllowed = true only if you will run firmware update. 90 | //public void connectAndConfigure(final Context context, final Device currentUsedDevice, final ConfigureListener configureListener, final boolean firmwareUpdateAllowed) { 91 | controller.connectAndConfigure(this, currentDev, ConfigurationAndFirmwareUpdateActivity.this, firmwareUpdateAlowedMode); 92 | 93 | // !!! if not needed firmware update use firmwareUpdateAllowed = false 94 | } 95 | 96 | @Override 97 | public void onConfigurationStarted() { 98 | onConnectionStarted(); 99 | if (firmwareUpdateAlowedMode) { 100 | showFirmwareScreen_LoadingVersionInfo(); 101 | } 102 | } 103 | 104 | private int configInProgressFileCounter = 0; 105 | 106 | @Override 107 | public void onConfigurationInProgress(PaymentFlowController.ConfigProgressState state, String message) { 108 | progress_text.setText("Processing..."); 109 | switch (state) { 110 | case FW_UPDATE_IN_PROGRESS: 111 | // we have to display conditionally also firmware update message witch some params 112 | message_text.setText(getString(R.string.general_firmware_update_pending, 113 | AcceptSDK.getTerminalInfo() != null ? AcceptSDK.getTerminalInfo().firmwareVersion : "-", 114 | AcceptSDK.getCurrentVersionOfSavedFirmwareInBackend() != null ? AcceptSDK.getCurrentVersionOfSavedFirmwareInBackend().getFwNumber() : "-")); 115 | return; 116 | case CONFIGURATION_UPDATE_FILE_COUNTER: 117 | // because here can be received during FW update also currentUsedDevice config events(if currentUsedDevice not updated config yet) 118 | message_text.setText(state + " (File " + ++configInProgressFileCounter + ")"); 119 | return; 120 | default: 121 | message_text.setText("Config update"); 122 | } 123 | } 124 | 125 | @Override 126 | public void onConfigureSuccess(boolean restarted) { 127 | progress_text.setText(" "); 128 | if (firmwareUpdateAlowedMode) { 129 | message_text.setText("New firmware installed successfully"); 130 | } 131 | else { 132 | message_text.setText("New configuration installed successfully"); 133 | if(restarted){ 134 | message_text.setText("New configuration installed successfully, \n please wait for restart"); 135 | } 136 | } 137 | finishedUpdate = true; 138 | if (restarted) 139 | cancelButton.setText("Restart done"); 140 | else 141 | cancelButton.setText("Done"); 142 | 143 | setResult(RESULT_OK); 144 | } 145 | 146 | @Override 147 | public void onConfigureError(PaymentFlowController.Error error, String errorMessage) { 148 | if (!finishedUpdate) 149 | showFailScreen(error, errorMessage); 150 | } 151 | 152 | private void showFirmwareScreen_LoadingVersionInfo() { 153 | progress_text.setText("PROGRESS_STATE_CONTACTING"); 154 | message_text.setText("Downloading firmware please wait"); 155 | } 156 | 157 | private void showFailScreen(PaymentFlowController.Error error, String errorMessage) { 158 | progress_text.setText("=ERROR="); 159 | message_text.setText("Pairing: connect failed"); 160 | if (error != null) 161 | progress_text.setText(error.name()); 162 | 163 | if (!TextUtils.isEmpty(errorMessage)) 164 | message_text.setText("Pairing: connect failed"); 165 | } 166 | 167 | public void onConnectionStarted() { 168 | Log.d(TAG, "onConnectionStarted"); 169 | progress_text.setText("CONNECTING"); 170 | message_text.setText("Pairing: connecting"); 171 | } 172 | 173 | @Override 174 | protected void onDestroy() { 175 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 176 | controller = null; 177 | finish(); 178 | super.onDestroy(); 179 | } 180 | 181 | @Override 182 | public void onBackPressed() { 183 | setResult(RESULT_CANCELED); 184 | super.onBackPressed(); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_thyron/java/de/wirecard/accept/sample/MenuActivity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Wirecard. All rights reserved. 3 | *

4 | * Accept SDK for Android 5 | */ 6 | package de.wirecard.accept.sample; 7 | 8 | import android.widget.Toast; 9 | 10 | import java.util.List; 11 | 12 | import de.wirecard.accept.extension.refactor.AcceptThyronPaymentFlowController; 13 | import de.wirecard.accept.sdk.extensions.Device; 14 | import de.wirecard.accept.sdk.extensions.PaymentFlowController; 15 | 16 | 17 | public class MenuActivity extends AbstractSpireMenuActivity { 18 | 19 | 20 | void discoverDevices() { 21 | 22 | //>>>>>>>>>> 1. create controller instance 23 | final AcceptThyronPaymentFlowController controller = new AcceptThyronPaymentFlowController();//default is BT, contactLessSupported = true 24 | 25 | //>>>>>>>>>> 2. call discovery devices 26 | //like first we have to call discover devices to get list of paired device from smartphone 27 | controller.discoverDevices(getApplicationContext(), new PaymentFlowController.SpireDiscoverDelegate() { 28 | @Override 29 | public void onDiscoveryError(PaymentFlowController.DiscoveryError discoveryError, String s) { 30 | //Check DiscoveryError enum states for translations 31 | Toast.makeText(getApplicationContext(), "Check bluetooth settings and enable bluetooth: " + discoveryError.name(), Toast.LENGTH_LONG).show(); 32 | } 33 | 34 | @Override 35 | public void onDiscoveredDevices(List list, final PaymentFlowController.SelectDeviceDelegate selectDeviceDelegate) { 36 | //received all paired devices from smart phone 37 | if (list == null || list.isEmpty()) { 38 | Toast.makeText(getApplicationContext(), "Settings: list of bounded devices empty, please pair terminal before.", Toast.LENGTH_LONG).show(); 39 | return; 40 | } 41 | if (list.size() == 1) {// just one device 42 | currentUsedDevice = list.get(0); 43 | Toast.makeText(getApplicationContext(), "Settings: one device detected.", Toast.LENGTH_LONG).show(); 44 | selectDeviceDelegate.onDeviceSelected(currentUsedDevice); 45 | return; 46 | } 47 | 48 | if (list.size() > 1 && currentUsedDevice != null) 49 | for (Device dev : list) 50 | if (currentUsedDevice.equals(dev)) { 51 | selectDeviceDelegate.onDeviceSelected(currentUsedDevice); 52 | return;// because its same as currently used 53 | } 54 | 55 | //else select manually using UI selector 56 | showSpireBoundedDevicesChooserDialog(MenuActivity.this, list, selectDeviceDelegate); 57 | } 58 | }); 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_thyron/java/de/wirecard/accept/sample/PaymentFlowActivity.java: -------------------------------------------------------------------------------- 1 | package de.wirecard.accept.sample; 2 | 3 | import android.text.TextUtils; 4 | import android.view.View; 5 | 6 | import java.util.List; 7 | 8 | import de.wirecard.accept.extension.refactor.AcceptThyronPaymentFlowController; 9 | import de.wirecard.accept.sdk.AcceptSDK; 10 | import de.wirecard.accept.sdk.L; 11 | import de.wirecard.accept.sdk.extensions.Device; 12 | import de.wirecard.accept.sdk.extensions.PaymentFlowController; 13 | 14 | public class PaymentFlowActivity extends AbstractCardPaymentFlowActivity { 15 | 16 | @Override 17 | PaymentFlowController createNewController() { 18 | // this is just feture because of supporting more terminals (flavours) 19 | 20 | /** 21 | * boolean supportContactless, boolean sepa, boolean usb 22 | */ 23 | return new AcceptThyronPaymentFlowController(((Application) getApplicationContext()).contactless, isSepa(), ((Application) getApplicationContext()).usb); 24 | } 25 | 26 | @Override 27 | boolean isSignatureConfirmationInApplication() { 28 | return false; 29 | } 30 | 31 | @Override 32 | boolean isRequiredPermissionOnStart() { 33 | return false; 34 | } 35 | 36 | @Override 37 | void startPaymentFlow(Device device, long amount) throws IllegalStateException { 38 | if (isSepa()) { // in case its sepa payment 39 | ((AcceptThyronPaymentFlowController) paymentFlowController).startSepaPaymentFlow(device, amount, getAmountCurrency(), this); 40 | return; 41 | } 42 | if (cashBack != AcceptSDK.CashBack.off) { // in case cashback will be supported 43 | //cashBack amount is set in AbstractPaymentFlowActivity.beforePayment() 44 | ((AcceptThyronPaymentFlowController) paymentFlowController).startCashBackPaymentFlow(device, cashBack, this); 45 | return; 46 | } 47 | //default is normal card payment using spire SPm2 terminal 48 | paymentFlowController.startPaymentFlow(device, amount, getAmountCurrency(), this); 49 | } 50 | 51 | PaymentFlowController.DiscoverDelegate getDiscoverDelegate() { 52 | return new PaymentFlowController.SpireDiscoverDelegate() { 53 | 54 | @Override 55 | public void onDiscoveryError(final PaymentFlowController.DiscoveryError error, final String technicalMessage) { 56 | L.e(TAG, ">>> onDiscoveryError"); 57 | runOnUiThreadIfNotDestroyed(new Runnable() { 58 | @Override 59 | public void run() { 60 | showProgress(-1, false); 61 | PaymentFlowDialogs.showTerminalDiscoveryError(PaymentFlowActivity.this, error, technicalMessage, new View.OnClickListener() { 62 | @Override 63 | public void onClick(View v) { 64 | //finish(); 65 | } 66 | }); 67 | } 68 | }); 69 | } 70 | 71 | @Override 72 | public void onDiscoveredDevices(final List devices, final PaymentFlowController.SelectDeviceDelegate selectDeviceDelegate) { 73 | L.e(TAG, ">>> onDiscoveredDevices"); 74 | runOnUiThreadIfNotDestroyed(new Runnable() { 75 | @Override 76 | public void run() { 77 | showProgress(-1, false); 78 | if (devices.isEmpty()) { 79 | PaymentFlowDialogs.showNoDevicesError(PaymentFlowActivity.this, new View.OnClickListener() { 80 | @Override 81 | public void onClick(View v) { 82 | //finish(); 83 | } 84 | }); 85 | return; 86 | } 87 | if (devices.size() == 1) { 88 | currentDevice = devices.get(0); 89 | selectDeviceDelegate.onDeviceSelected(currentDevice); 90 | return; 91 | } 92 | 93 | //DEMO APP SPECIFIC: if list of devices contains device from bundle parameters...from previous menu activity send as paramter 94 | if (currentDevice != null && devices.size() > 1) { 95 | for (Device d: devices){ 96 | if(d.equals(currentDevice)){ 97 | selectDeviceDelegate.onDeviceSelected(currentDevice); 98 | return; 99 | } 100 | } 101 | } 102 | 103 | PaymentFlowDialogs.showTerminalChooser(PaymentFlowActivity.this, devices, new PaymentFlowDialogs.DeviceToStringConverter() { 104 | @Override 105 | public String displayNameForDevice(Device device) { 106 | if (TextUtils.isEmpty(device.displayName)) { 107 | return device.id; 108 | } 109 | return device.displayName; 110 | } 111 | }, new PaymentFlowDialogs.TerminalChooserListener() { 112 | @Override 113 | public void onDeviceSelected(Device device) { 114 | currentDevice = device; 115 | selectDeviceDelegate.onDeviceSelected(currentDevice); 116 | } 117 | 118 | @Override 119 | public void onSelectionCanceled() { 120 | finish(); 121 | } 122 | }); 123 | } 124 | }); 125 | } 126 | }; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /demo/demo/sample/src/flavor_thyron/res/layout/activity_firmware_update.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 | 22 | 23 | 32 | 33 |