Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Streamlining Payments on Mobile

Streamlining Payments on Mobile

Payments on Mobile is not an easy task but it is certainly one of the most important in a commerce application. At Capitaine Train it was a very important part of our mission to help people purchase their train tickets easily and we improved the paying experience multiple times since the first release of the application.

In this talk, we will see how to build a payment process from scratch: from the simplest payment form to the more evolved one, handling 3DSecure, how to use fingerprint to streamline even more the process, handling multiple payment methods.

Video: https://www.youtube.com/watch?v=kwruiDw31T0

Mathieu Calba

April 11, 2017
Tweet

More Decks by Mathieu Calba

Other Decks in Programming

Transcript

  1. Keep It Stupid and Simple Payment Account Number Expiration Date

    CVV Holder Name 4111 1111 1111 1111 04/17 111 Bill Murray
  2. Keep It Stupid and Simple Payment Account Number Expiration Date

    CVV Holder Name Terms of Sales 4111 1111 1111 1111 04/17 111 Bill Murray I agree with the Terms of Services of Android Makers
  3. Keep It Stupid and Simple Payment Account Number Expiration Date

    CVV Holder Name Terms of Sales Pay Button 4111 1111 1111 1111 04/17 111 Bill Murray I agree with the Terms of Services of Android Makers PAY 123.00 €
  4. Keep It Stupid and Simple Payment Account Number Expiration Date

    CVV Holder Name Terms of Sales Pay Button 4111 1111 1111 1111 04/17 111 Bill Murray I agree with the Terms of Services of Android Makers PAY 123.00 €
  5. Step 1 - Simplest Form <android.support.constraint.ConstraintLayout ... > <EditText android:id="@+id/edit_card_number"

    android:hint="Card Number" ... /> <EditText android:id="@+id/edit_expiration_month" android:hint="Expiration Month" ... /> ... <CheckBox android:id="@+id/check_box_terms" android:text="I accept the terms &amp; conditions of AndroidMakers" ... /> <Button android:id="@+id/bt_pay" android:text="Pay" ... /> </android.support.constraint.ConstraintLayout>
  6. Step 1 - Simplest Form <android.support.constraint.ConstraintLayout ... > <EditText android:id="@+id/edit_card_number"

    android:hint="Card Number" ... /> <EditText android:id="@+id/edit_expiration_month" android:hint="Expiration Month” ... /> ... <CheckBox android:id="@+id/check_box_terms" android:text="I accept the terms &amp; conditions of AndroidMakers" ... /> <Button android:id="@+id/bt_pay" android:text="Pay" ... /> </android.support.constraint.ConstraintLayout>
  7. Step 1 - Simplest Form Loose sense of what are

    we filling We can input whatever we want
  8. Step 1 - Simplest Form Loose sense of what are

    we filling We can input whatever we want We have to manually select the next field
  9. Step 1 - Simplest Form Loose sense of what are

    we filling We can input whatever we want We have to manually select the next field Keyboard not showing up automatically
  10. Step 1 - Simplest Form Loose sense of what are

    we filling We can input whatever we want We have to manually select the next field Keyboard not showing up automatically
  11. Step 2 - Minimal Form <android.support.design.widget.TextInputLayout android:id="@+id/card_number" android:hint="Card Number" ...

    > <android.support.design.widget.TextInputEditText android:id="@+id/edit_card_number" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.TextInputLayout> Material Components for Android compile 'com.android.support:design:25.3.0' Keep sense of what are we filling
  12. Step 2 - Minimal Form InputType Bit masking defining the

    basic content type of a text in an Editable object. Used by IME to determine which keyboard to display. Limit the input
  13. Step 2 - Minimal Form 4 classes of InputType: TYPE_CLASS_DATETIME

    TYPE_CLASS_NUMBER TYPE_CLASS_PHONE TYPE_CLASS_TEXT Limit the input
  14. Step 2 - Minimal Form Many flags & variations: TYPE_DATETIME_VARIATION_DATE

    TYPE_DATETIME_VARIATION_NORMAL TYPE_DATETIME_VARIATION_TIME TYPE_NUMBER_FLAG_DECIMAL TYPE_NUMBER_FLAG_SIGNED TYPE_NUMBER_VARIATION_NORMAL TYPE_TEXT_FLAG_AUTO_COMPLETE TYPE_TEXT_FLAG_AUTO_CORRECT TYPE_TEXT_FLAG_CAP_CHARACTERS Limit the input TYPE_TEXT_FLAG_CAP_SENTENCES TYPE_TEXT_FLAG_CAP_WORDS TYPE_TEXT_FLAG_MULTI_LINE TYPE_TEXT_FLAG_NO_SUGGESTIONS TYPE_TEXT_VARIATION_PASSWORD TYPE_TEXT_VARIATION_PERSON_NAME TYPE_TEXT_VARIATION_PHONETIC TYPE_TEXT_VARIATION_URI ...
  15. Step 2 - Minimal Form TextView.setInputType(int type) Only change the

    input capabilities (keyboard, pasting, etc). Does NOT validate the input. Limit the input
  16. Step 2 - Minimal Form Many flags & variations: date

    datetime none number numberDecimal numberSigned textAutoComplete textAutoCorrect textCapCharacters textCapSentences Limit the input textCapWords textImeMultiLine textMultiLine textNoSuggestions textPassword textPersonName textPhonetic textVisiblePassword time ...
  17. Step 2 - Minimal Form Expiration Date TYPE_CLASS_DATETIME | TYPE_DATETIME_VARIATION_DATE

    or date Payment Account Number & CVV TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_NORMAL or number Card Holder TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PERSON_NAME or textPersonName Limit the input
  18. Step 2 - Minimal Form Expiration Date TYPE_CLASS_DATETIME | TYPE_DATETIME_VARIATION_DATE

    or date Payment Account Number & CVV TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_NORMAL or number Card Holder TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PERSON_NAME or textPersonName Limit the input
  19. Step 2 - Minimal Form Expiration Date TYPE_CLASS_DATETIME | TYPE_DATETIME_VARIATION_DATE

    or date Payment Account Number & CVV TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_NORMAL or number Card Holder TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PERSON_NAME or textPersonName Limit the input
  20. Step 2 - Minimal Form Expiration Date TYPE_CLASS_DATETIME | TYPE_DATETIME_VARIATION_DATE

    or date Payment Account Number & CVV TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_NORMAL or number Card Holder TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PERSON_NAME or textPersonName Limit the input
  21. Step 2 - Minimal Form TextView.setImeOptions (int imeOptions) Extend the

    type information for an Editor to improve IME integration with the application. Moving between inputs
  22. Step 2 - Minimal Form Many actions & flags: IME_ACTION_DONE

    IME_ACTION_GO IME_ACTION_NEXT IME_ACTION_NONE IME_ACTION_PREVIOUS IME_ACTION_SEARCH IME_ACTION_SEND IME_ACTION_UNSPECIFIED Moving between inputs IME_FLAG_FORCE_ASCII IME_FLAG_NAVIGATE_NEXT IME_FLAG_NAVIGATE_PREVIOUS IME_FLAG_NO_ACCESSORY_ACTION IME_FLAG_NO_ENTER_ACTION IME_FLAG_NO_EXTRACT_UI IME_FLAG_NO_FULLSCREEN
  23. Step 2 - Minimal Form Many actions & flags: actionDone

    actionGo actionNext actionNone actionPrevious actionSearch actionSend actionUnspecified Moving between inputs flagForceAscii flagNavigateNext flagNavigatePrevious flagNoAccessoryAction flagNoEnterAction flagNoExtractUi flagNoFullscreen normal
  24. Step 2 - Minimal Form TextView.setOnEditorActionListener (OnEditorActionListener l) Help you

    react on the Keyboard action key press Moving between inputs
  25. Step 2 - Minimal Form Going Next (all except Card

    Holder) IME_ACTION_NEXT or actionNext Done (Card Holder) IME_ACTION_DONE or actionDone Moving between inputs
  26. Step 2 - Minimal Form android:windowSoftInputMode Activity attribute defining how

    it interacts with the window containing the keyboard. Showing/Hiding Keyboard
  27. Step 2 - Minimal Form Can be a state and/or

    adjust. state: state of the keyboard when Activity becomes visible stateUnspecified (default) stateUnchanged stateHidden stateAlwaysHidden stateVisible stateAlwaysVisible Showing/Hiding Keyboard adjust: adjustments made to the Activity’s main Window adjustUnspecified (default) adjustResize adjustPan
  28. Step 2 - Minimal Form Can be a state and/or

    adjust. state: state of the keyboard when Activity becomes visible stateUnspecified (default) stateUnchanged stateHidden stateAlwaysHidden stateVisible stateAlwaysVisible Showing/Hiding Keyboard adjust: adjustments made to the Activity’s main Window adjustUnspecified (default) adjustResize adjustPan
  29. Step 2 - Minimal Form Hide the keyboard if shown

    when the user tap the terms and conditions checkbox Showing/Hiding Keyboard
  30. Step 2 - Minimal Form On demand InputMethodManager.showSoftInput(View view, int

    flags) InputMethodManager.hideSoftInputFromWindow (IBinder windowToken, int flags) Showing/Hiding Keyboard
  31. Step 2 - Minimal Form On demand public static void

    hideSoftKeyboard(Context context, View view) { InputMethodManager imm = (InputMethodManager) context. getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } public static void showSoftKeyboard(Context context, View view) { InputMethodManager imm = (InputMethodManager) context. getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(view, 0); } Showing/Hiding Keyboard
  32. Step 2 - Minimal Form On demand public static void

    hideSoftKeyboard(Context context, View view) { InputMethodManager imm = (InputMethodManager) context. getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } public static void showSoftKeyboard(Context context, View view) { InputMethodManager imm = (InputMethodManager) context. getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(view, 0); } Showing/Hiding Keyboard
  33. Step 2 - Minimal Form On demand public static void

    hideSoftKeyboard(Context context, View view) { InputMethodManager imm = (InputMethodManager) context. getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } public static void showSoftKeyboard(Context context, View view) { InputMethodManager imm = (InputMethodManager) context. getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(view, 0); } Showing/Hiding Keyboard
  34. Step 3 - Improving Expiration Date Spinner are not suitable

    for month/year selection on mobile due to the large amount of possibilities Data Validation
  35. Step 3 - Improving Expiration Date public interface TextWatcher extends

    NoCopySpan { public void beforeTextChanged(CharSequence text, int start, int count, int after); public void onTextChanged(CharSequence text, int start, int before, int count); public void afterTextChanged(Editable text); } Data Validation
  36. Step 3 - Improving Expiration Date public interface TextWatcher extends

    NoCopySpan { public void beforeTextChanged(CharSequence text, int start, int count, int after); public void onTextChanged(CharSequence text, int start, int before, int count); public void afterTextChanged(Editable text); } Data Validation
  37. Step 3 - Improving Expiration Date public interface TextWatcher extends

    NoCopySpan { public void beforeTextChanged(CharSequence text, int start, int count, int after); public void onTextChanged(CharSequence text, int start, int before, int count); public void afterTextChanged(Editable text); } Data Validation
  38. Step 3 - Improving Expiration Date public interface TextWatcher extends

    NoCopySpan { public void beforeTextChanged(CharSequence text, int start, int count, int after); public void onTextChanged(CharSequence text, int start, int before, int count); public void afterTextChanged(Editable text); } Data Validation
  39. Step 3 - Improving Expiration Date private ForegroundColorSpan mErrorSpan =

    new ForegroundColorSpan(Color.RED)); private boolean mIsEditing; @Override public void afterTextChanged(Editable text) { if (mIsEditing) { return; } mIsEditing = true; text.removeSpan(mErrorSpan); String expirationMonth = text.toString(); if (isExpirationMonthLengthValid(expirationMonth)) { if (!isExpirationMonthValid(expirationMonth)) { text.setSpan(mErrorSpan, 0, LENGTH_EXPIRATION_MONTH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mEditView.setContentDescription("incorrect card expiration month"); mEditView.announceForAccessibility(mEditView.getContentDescription()); } } mIsEditing = false; } Data Validation
  40. Step 3 - Improving Expiration Date private ForegroundColorSpan mErrorSpan =

    new ForegroundColorSpan(Color.RED)); private boolean mIsEditing; @Override public void afterTextChanged(Editable text) { if (mIsEditing) { return; } mIsEditing = true; text.removeSpan(mErrorSpan); String expirationMonth = text.toString(); if (isExpirationMonthLengthValid(expirationMonth)) { if (!isExpirationMonthValid(expirationMonth)) { text.setSpan(mErrorSpan, 0, LENGTH_EXPIRATION_MONTH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mEditView.setContentDescription("incorrect card expiration month"); mEditView.announceForAccessibility(mEditView.getContentDescription()); } } mIsEditing = false; } Data Validation
  41. Step 3 - Improving Expiration Date private ForegroundColorSpan mErrorSpan =

    new ForegroundColorSpan(Color.RED)); private boolean mIsEditing; @Override public void afterTextChanged(Editable text) { if (mIsEditing) { return; } mIsEditing = true; text.removeSpan(mErrorSpan); String expirationMonth = text.toString(); if (isExpirationMonthLengthValid(expirationMonth)) { if (!isExpirationMonthValid(expirationMonth)) { text.setSpan(mErrorSpan, 0, LENGTH_EXPIRATION_MONTH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mEditView.setContentDescription("incorrect card expiration month"); mEditView.announceForAccessibility(mEditView.getContentDescription()); } } mIsEditing = false; } Data Validation
  42. Step 3 - Improving Expiration Date private ForegroundColorSpan mErrorSpan =

    new ForegroundColorSpan(Color.RED)); private boolean mIsEditing; @Override public void afterTextChanged(Editable text) { if (mIsEditing) { return; } mIsEditing = true; text.removeSpan(mErrorSpan); String expirationMonth = text.toString(); if (isExpirationMonthLengthValid(expirationMonth)) { if (!isExpirationMonthValid(expirationMonth)) { text.setSpan(mErrorSpan, 0, LENGTH_EXPIRATION_MONTH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mEditView.setContentDescription("incorrect card expiration month"); mEditView.announceForAccessibility(mEditView.getContentDescription()); } } mIsEditing = false; } Data Validation
  43. Step 3 - Improving Expiration Date private ForegroundColorSpan mErrorSpan =

    new ForegroundColorSpan(Color.RED)); private boolean mIsEditing; @Override public void afterTextChanged(Editable text) { if (mIsEditing) { return; } mIsEditing = true; text.removeSpan(mErrorSpan); String expirationMonth = text.toString(); if (isExpirationMonthLengthValid(expirationMonth)) { if (!isExpirationMonthValid(expirationMonth)) { text.setSpan(mErrorSpan, 0, LENGTH_EXPIRATION_MONTH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mEditView.setContentDescription("incorrect card expiration month"); mEditView.announceForAccessibility(mEditView.getContentDescription()); } } mIsEditing = false; } Data Validation
  44. Step 3 - Improving Expiration Date Lot of space wasted,

    maybe we could merge the expiration month and year fields into one ‣ Consolidate same kind of data together ‣ Allows us to validate the month with the year ‣ Make room for CVV on the right and Pay button moves up, making it always visible
  45. Step 3 - Improving Expiration Date Lot of space wasted,

    maybe we could merge the expiration month and year fields into one ‣ Consolidate same kind of data together ‣ Allows us to validate the month with the year ‣ Make room for CVV on the right and Pay button moves up, making it always visible
  46. Step 3 - Improving Expiration Date Lot of space wasted,

    maybe we could merge the expiration month and year fields into one ‣ Consolidate same kind of data together ‣ Allows us to validate the month with the year ‣ Make room for CVV on the right and Pay button moves up, making it always visible
  47. Step 3 - Improving Expiration Date Lot of space wasted,

    maybe we could merge the expiration month and year fields into one ‣ Consolidate same kind of data together ‣ Allows us to validate the month with the year ‣ Make room for CVV on the right and Pay button moves up, making it always visible
  48. Step 3 - Improving Expiration Date Using formatting pattern MM/YY

    Without letting the user enter / Optimising fields distribution
  49. Step 3 - Improving Expiration Date private boolean mIsEditing; @Override

    public void afterTextChanged(Editable text) { if (mIsEditing) { return; } mIsEditing = true; // Remove filters because they prevent us from inserting // non-digit characters when inputType is set to "number" InputFilter[] inputFilters = text.getFilters(); text.setFilters(InputFilterUtils.EMPTY_FILTERS); [...] mIsEditing = false; } Optimising fields distribution
  50. Step 3 - Improving Expiration Date @Override public void afterTextChanged(Editable

    text) { [...] // 1. We extract the expirationMonth and expirationYear String noSpaceText = getDigitOnlyText(text); int length = noSpaceText.length(); String expirationMonth = noSpaceText. substring(0, Math.min(length, LENGTH_EXPIRATION_PARTIAL)); String expirationYear = ""; if (noSpaceText.length() > LENGTH_EXPIRATION_PARTIAL) { expirationYear = noSpaceText.substring( LENGTH_EXPIRATION_PARTIAL, Math.min(length, LENGTH_EXPIRATION)); } [...] } Optimising fields distribution
  51. Step 3 - Improving Expiration Date @Override public void afterTextChanged(Editable

    text) { [...] // 2. We try to format the newly entered text here CharSequence base = getFormattedExpirationDate( expirationMonth, expirationYear); text.removeSpan(mErrorSpan); text.replace(0, text.length(), base); // 3. We handle the error in this field like in previous slide // 4. Re-install filters text.setFilters(inputFilters); mIsEditing = false; } Optimising fields distribution
  52. Step 3 - Improving Expiration Date @Override public void afterTextChanged(Editable

    text) { [...] // 2. We try to format the newly entered text here CharSequence base = getFormattedExpirationDate( expirationMonth, expirationYear); text.removeSpan(mErrorSpan); text.replace(0, text.length(), base); // 3. We handle the error in this field like in previous slide // 4. Re-install filters text.setFilters(inputFilters); mIsEditing = false; } Optimising fields distribution
  53. Step 3 - Improving Expiration Date @Override public void afterTextChanged(Editable

    text) { [...] // 2. We try to format the newly entered text here CharSequence base = getFormattedExpirationDate( expirationMonth, expirationYear); text.removeSpan(mErrorSpan); text.replace(0, text.length(), base); // 3. We handle the error in this field like in previous slide // 4. Re-install filters text.setFilters(inputFilters); mIsEditing = false; } Optimising fields distribution
  54. Step 3 - Improving Expiration Date @Override public void afterTextChanged(Editable

    text) { [...] if (isMonthValid && isYearValid) { if (isExpirationDateValid(month, year)) { mCvvView.requestFocus(); CharSequence text = mCvvEditView.getText(); mCvvEditView.setSelection(text.length()); } } mIsEditing = false; } Auto-advance to the next field
  55. Step 4 - Improving PAN Many types of Cards, multiple

    formats Visa - 4xxx xxxx xxxx xxxx Formatting
  56. Step 4 - Improving PAN Many types of Cards, multiple

    formats Visa - 4xxx xxxx xxxx xxxx Mastercard - 51xx xxxx xxxx xxxx -> 55xx xxxx xxxx xxxx Formatting
  57. Step 4 - Improving PAN Many types of Cards, multiple

    formats Visa - 4xxx xxxx xxxx xxxx Mastercard - 51xx xxxx xxxx xxxx to 55xx xxxx xxxx xxxx American Express - 34xx xxxxx xxxxx and 37xx xxxxx xxxxx Formatting
  58. Step 4 - Improving PAN Many types of Cards, multiple

    formats Visa - 4xxx xxxx xxxx xxxx Mastercard - 51xx xxxx xxxx xxxx to 55xx xxxx xxxx xxxx American Express - 34xx xxxxx xxxxx and 37xx xxxxx xxxxx and many others: https://en.wikipedia.org/wiki/Payment_card_number Formatting
  59. Step 4 - Improving PAN Each type must validate the

    Luhn Algorithm: public static boolean checkLuhnValidity(String number) { int sum = 0; boolean isOdd = true; for (int i = number.length() - 1; i >= 0; i--) { String digitString = number.substring(i, i + 1); int digit = Integer.parseInt(digitString); sum += isOdd ? digit : digit / 5 + (digit << 1) % 10; isOdd = !isOdd; } return sum % 10 == 0; } Data Validation
  60. Step 4 - Improving PAN Detect type of card Validate

    it Display type of card Handle CVV length
  61. Step 4 - Improving PAN Detect type of card Validate

    it Display type of card Handle CVV length Display icon for each fields
  62. Step 4 - Improving PAN Detect type of card Validate

    it Display type of card Handle CVV length Display icon for each fields
  63. Keep it Safe for your Users (and for you) WindowManager.LayoutParams.FLAG_SECURE

    Allows to configure a Window as secure Blocking screen capture
  64. Keep it Safe for your Users (and for you) Before

    calling Activity.setContentView(), add: getWindow().setFlags( LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE) Blocking screen capture
  65. Keep it Safe for your Users (and for you) A

    webpage hosted by the bank to validate the identity of the person using the credit card Totally outside of our control and the control of your provider of payment 3D Secure
  66. Keep it Safe for your Users (and for you) Webpage

    can take forever to load or can fail to load without any message Need to inform the user what’s happening Adding a permanent SnackBar or other in layout message indicating that the process is in progress, and what to do if nothing happens after some time 3D Secure
  67. Keep it Contextual Let the User know what he is

    paying Display the price directly on the Pay button
  68. Adapt to your Users Be frictionless on the payment Accept

    the most payment methods Adapt to your marketed countries (PayPal in Italy, SOFORT in Germany, etc) Use Android Pay if it’s available in your country (No France, thanks Google ) Remember their preferred payment method Multiple Payment Methods
  69. Adapt to your Users How to adapt the UI with

    multiple payment methods and keeping it clean? No universal good way Depends on your business and what you want to optimise for Multiple Payment Methods
  70. Adapt to your Users Expanding list with one entry per

    payment method Multiple Payment Methods
  71. Adapt to your Users List with your preferred way of

    paying or the mostly used at the top promoted at the top Multiple Payment Methods
  72. Adapt to your Users Directly select the preferred way of

    paying (or the mostly used) And add an access to other payment methods Multiple Payment Methods
  73. –Me, right now “The better way to make a user

    fill in a form is to fill it for him”
  74. Remember for Them Suggest saving payment cards on your server

    for recurring users, but do not force them to do so The perfect moment to suggest it is just after a payment succeed
  75. Remember for Them Do it on the server, not locally,

    as some public organisations do not allow you to do so Server needs to be certified with PCI-DSS at a very high level, not an easy and quick thing to obtain
  76. Remember for Them A saved payment card is probably the

    preferred way of paying, so make it the most accessible one
  77. Stay One Touch Away Do not force the user to

    use his fingerprint Fingerprint API
  78. Stay One Touch Away API 23 min, but compatibility version

    available in support library Requires android.permission.USE_FINGERPRINT (not dangerous) Fingerprint API
  79. Stay One Touch Away FingerprintManager Detect presence of Fingerprint hardware

    CTS enforce the presence of an hardware backed KeyStore for it to be compatible with the Android API Detect if any fingerprint is enrolled Authenticate a FingerprintManager.CryptoObject Fingerprint API
  80. Stay One Touch Away FingerprintManager.CryptoObject Wrapper for using crypto objects

    with FingerprintManager Works on Cipher, Mac, and Signature objects Fingerprint API
  81. Stay One Touch Away Mac Checks integrity of information transmitted

    over or stored in an unreliable medium, using a secret key known by each entities that want to read/write the information Fingerprint API
  82. Stay One Touch Away Signature Provides digital signature algorithm Used

    for authentication and integrity assurance of digital data Fingerprint API
  83. Stay One Touch Away Fingerprint API with Signature - enrolment

    My Application Server Payment Cards Fingerprint Manager create Signature for a PrivateKey 1 authenticate Signature 2 register Signature 3 save Signature 4 KeyStore
  84. Stay One Touch Away Fingerprint API with Signature - payment

    My Application Server Payment Cards Fingerprint Manager create Signature for a PrivateKey 1 authenticate Signature 2 pay with Signature 3 validate Signature 4 5 access Payment Card KeyStore
  85. Stay One Touch Away Cipher Cryptographic cipher for encryption and

    decryption Needs a transformation, aka the operations you want to apply to your input to get the output Fingerprint API
  86. Stay One Touch Away Fingerprint API with Cipher - encryption

    My Application KeyStore Fingerprint Manager prepare Cipher with a SecretKey in encrypt mode 1 authenticate Cipher 2 Database save Cipher.getIV() and encrypted Data 4 encrypt Data with authenticated Cipher 3
  87. Stay One Touch Away Fingerprint API with Cipher - encryption

    My Application KeyStore Server Payment Cards Fingerprint Manager prepare Cipher with a SecretKey and the IV in decrypt mode 2 authenticate Cipher 3 pay with decrypted Data 6 Database get the IV for this Data 1 decrypt Data with Cipher 5 get the encrypted Data 4
  88. Stay One Touch Away Consult a security expert to know

    exactly what you can do with storing credit card data! Fingerprint API
  89. Stay One Touch Away FingerprintManager.authenticate( CryptoObject crypto, int flags, CancellationSignal

    cancel, AuthenticationCallback callback, Handler handler) Fingerprint API
  90. Stay One Touch Away public static abstract class AuthenticationCallback {

    public void onAuthenticationError(int errorCode, CharSequence errString) { } public void onAuthenticationHelp(int helpCode, CharSequence helpString) { } public void onAuthenticationSucceeded(AuthenticationResult result) { } public void onAuthenticationFailed() { } public void onAuthenticationAcquired(int acquireInfo) { } }; Fingerprint API