{"title":"Card reader solution for Android","category":"default","creationDate":1776961627,"content":"<p>With our Card reader on Android solution you can accept mobile in-person payments using a card reader as the payment interface, and process these payments on the plataforma de pagamentos da Adyen.<\/p>\n<p>The card reader is connected with an Android mobile device through Bluetooth, or through USB using a dock. On the Android mobile device, payment requests are initiated from a POS app. On the card reader, the customer can tap, insert, or swipe their card, or use a digital wallet like Apple Pay.<\/p>\n<h2>Requirements<\/h2>\n<p>Before you begin, take into account the following requirements, limitations, and preparations.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">Requirement<\/th>\n<th style=\"text-align: left;\">Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\"><strong>Integration type<\/strong><\/td>\n<td style=\"text-align: left;\">You must have a POS app that is integrated with <a href=\"\/pt\/point-of-sale\/design-your-integration\/terminal-api\/\">Terminal API<\/a>.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><strong><a href=\"\/pt\/development-resources\/api-credentials\/\">API credentials<\/a><\/strong><\/td>\n<td style=\"text-align: left;\">You need the following API credentials: <ul><li markdown=\"1\">To get the SDK, you must have an API credential with an API key and only the <strong>Allow SDK download for POS developers<\/strong> role.<\/li> <li markdown=\"1\">To establish a communication session, you must have an API credential with an API key, a client key, and the  <strong>Checkout webservice<\/strong> role.<\/li><\/ul><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><strong><a href=\"\/pt\/development-resources\/webhooks\">Webhooks<\/a><\/strong><\/td>\n<td style=\"text-align: left;\">To learn the outcome of refunds, set up Standard webhooks (if this hasn't been done already).<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><strong>Hardware<\/strong><\/td>\n<td style=\"text-align: left;\">You need: <ul><li markdown=\"1\">An Android commercial off-the-shelf (COTS) mobile device. Must not be a payment terminal.<\/li> <li markdown=\"1\">An NYC1 card reader from Adyen and optionally an <a href=\"\/pt\/point-of-sale\/user-manuals\/nyc1-with-dock\/\">NYC1 dock<\/a>. For PIN transactions your card reader needs to be an <a href=\"\/pt\/point-of-sale\/mobile-ios\/understand#pin-transaction-on-nyc1\">NYC1<\/a> model.<\/li><\/ul> See <a href=\"\/pt\/point-of-sale\/mobile-android\/requirements\">Android system requirements<\/a> for the full hardware and software requirements.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><strong>Limitations<\/strong><\/td>\n<td style=\"text-align: left;\">Check the countries\/regions, payment methods, and functionality that we <a href=\"\/pt\/point-of-sale\/ipp-mobile\">support<\/a> for Card reader on Android.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><strong>Setup steps<\/strong><\/td>\n<td style=\"text-align: left;\">Before you begin: <ul><li markdown=\"1\">Ask our <a href=\"https:\/\/ca-test.adyen.com\/ca\/ca\/contactUs\/support.shtml?form=other\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Support Team<\/a> to enable your Adyen test account for using our Mobile solutions.<\/li> <li markdown=\"1\">In your <a href=\"https:\/\/ca-test.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Customer Area<\/a>, <a href=\"\/pt\/point-of-sale\/managing-terminals\/order-terminals#sales-order-steps\">order<\/a> a test NYC1 card reader and a test card, and <a href=\"\/pt\/point-of-sale\/managing-terminals\/assign-terminals\">assign<\/a> the reader to your store. <li markdown=\"1\">If you want to disable PIN support for NYC1 card readers in the US from Mobile SDK for Android version <strong>2.9.0<\/strong> or later, contact our <a href=\"https:\/\/ca-test.adyen.com\/ca\/ca\/contactUs\/support.shtml?form=other\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Support Team<\/a> and ask them to disable PIN support on the company, merchant, or store level.<\/li><\/li><\/ul><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>How it works<\/h2>\n<div class=\"additional-info-block output-inline\">\n<div class=\"additional-info-block__body\"><p><strong>Sample app<\/strong><br \/>\nHit the ground running with our <a href=\"https:\/\/github.com\/Adyen\/adyen-pos-mobile-android\/tree\/main\/app-default\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Android sample app<\/a>.<\/p><\/div><\/div>\n\n<p>To build a Tap to Pay on Android solution:<\/p>\n<ol>\n<li>\n<p>Add the Mobile SDK for Android to your project, either using an API key.<\/p>\n<\/li>\n<li>\n<p>Implement a server-to-server API request to establish a secure communication session.<\/p>\n<\/li>\n<li>\n<p>In your POS app, enable the transaction functionality of the SDK.<\/p>\n<\/li>\n<li>\n<p>From your POS app, call the warmup function to speed up initiating transactions.<\/p>\n<\/li>\n<li>\n<p>In your POS app, implement handling payments using the SDK.<br \/>\nThis creates the following flow:<\/p>\n<ol>\n<li>Your Android POS app creates a Terminal API payment request, or receives a Terminal API payment request from your backend.<\/li>\n<li>The POS app passes the payment request to the Android Mobile SDK.<\/li>\n<li>The SDK initiates the transaction on the card reader.<br \/>\nTo complete the payment, the customer taps the card reader with their payment card or phone (or other device) that has a digital wallet like Apple Pay.<\/li>\n<li>The SDK passes the Terminal API payment response to the POS app.<\/li>\n<\/ol>\n<\/li>\n<li>\n<p>In your POS app, implement handling refunds using the SDK.<\/p>\n<\/li>\n<li>\n<p>If the same device will be used at multiple locations, implement clearing the communication session.<\/p>\n<\/li>\n<\/ol>\n<h2 id=\"add-sdk\">1. Add the SDK to your project<\/h2>\n<p>You can add the Mobile SDK for Android to your POS app through a private Adyen repository. To get access, you need to have an Adyen API key that is used only for the purpose of getting the SDK.<\/p>\n<div class=\"notices yellow\">\n<p>Our SDK only runs on Android 12 or later. You can still <a href=\"https:\/\/developer.android.com\/build\/manage-manifests#override_uses-sdk_for_imported_libraries\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">target earlier Android versions<\/a>, but our SDK will not initialize.<\/p>\n<\/div>\n<p>To add the Mobile SDK to your project, you need to create an API credential with an API key that only has the <strong>Allow SDK download for POS developers<\/strong> role.<\/p>\n<div class=\"notices green\">\n<p>This API key is only meant to be used to get access to the SDK repository. To make a <code>sessions<\/code> request, you need a <a href=\"#session\">different API key<\/a>.<\/p>\n<\/div>\n<p>You can share this API key with anybody in your team who needs to get the SDK, or you can create multiple API keys for internal use.<\/p>\n<p>To add the SDK to your project:<\/p>\n<ol>\n<li>\n<p>In your <a href=\"https:\/\/ca-test.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Customer Area<\/a> create an API credential with an API key:<\/p>\n<ol>\n<li>\n<p>Go to <strong>Developers<\/strong> &gt; <strong>API credentials<\/strong>, and select <strong>Create new credential<\/strong>.<\/p>\n<\/li>\n<li>\n<p>Under <strong>Payments<\/strong> &gt; <strong>Credential type<\/strong> select <strong>Web service user<\/strong> and then select <strong>Create credential<\/strong>.<\/p>\n<\/li>\n<li>\n<p>Under <strong>Server settings<\/strong> &gt; <strong>Authentication<\/strong> select the <strong>API key<\/strong> tab and then select <strong>Generate API key<\/strong>.<\/p>\n<\/li>\n<li>\n<p>Select the copy icon <i class=\"adl-icon-copy\"><\/i> and save your API key in a secure location.<\/p>\n<\/li>\n<li>\n<p>Go to <strong>Permissions<\/strong> &gt; <strong>Roles<\/strong> &gt; <strong>POS<\/strong>, select <strong>Allow SDK download for POS developers<\/strong>, and deselect any other permissions and roles.<\/p>\n<div class=\"notices green\">\n<p>Contact <a href=\"https:\/\/ca-test.adyen.com\/ca\/ca\/contactUs\/support.shtml?form=other\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Support Team<\/a> if you don't see the <strong>Allow SDK download for POS developers<\/strong> role.<\/p>\n<\/div>\n<\/li>\n<li>\n<p>Select <strong>Save changes<\/strong>.<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p>In the <code>repositories<\/code> block of your project, usually defined in your <code>settings.gradle<\/code> file, add the URL to the remote repository where the SDK is stored, and add the API key that you created in the previous step.<\/p>\n<pre><code class=\"language-kotlin\">dependencyResolutionManagement {\n    \/\/...\n    repositories {\n        google()\n        mavenCentral()\n        maven {\n            url = uri(\"https:\/\/pos-mobile-test.cdn.adyen.com\/adyen-pos-android\")\n            credentials(HttpHeaderCredentials::class) {\n                name = \"x-api-key\"\n                value = \"&lt;YOUR_API_KEY&gt;\"\n            }\n            authentication {\n                create&lt;HttpHeaderAuthentication&gt;(\"header\")\n            }\n        }\n    }\n}<\/code><\/pre>\n<\/li>\n<li>\n<p>In your project's <code>build.gradle<\/code> file, add the package dependencies.<\/p>\n<ul>\n<li>To find the latest <code>val version<\/code> check the <a href=\"\/pt\/point-of-sale\/firmware-release-notes?title%5B0%5D=Android%2BSDK%2Bon%2Bmobile\">release notes<\/a> for the Mobile SDK for Android.<\/li>\n<li>For the build type, note that <code>-debug<\/code> can only access the test environment, and <code>-release<\/code> can only access the live environment.<\/li>\n<li>In case of other custom build variants, use <code>&lt;buildVariantName&gt;Implementation 'com.adyen.ipp:pos-mobile-&lt;type&gt;:$version'<\/code> where <code>&lt;type&gt;<\/code> can be <strong>release<\/strong> for production builds, or <strong>debug<\/strong> for debug or development builds.<\/li>\n<\/ul>\n<pre><code class=\"language-groovy\">val version = 2.2.0\ndebugImplementation 'com.adyen.ipp:pos-mobile-debug:$version'\n\/\/ Be aware that importing additional modules will increase the size of your application.\n\/\/ To optimize your app's size and build times, only include the specific payment features you require.\ndebugImplementation 'com.adyen.ipp:payment-tap-to-pay-debug:$version'\ndebugImplementation 'com.adyen.ipp:payment-card-reader-debug:$version'<\/code><\/pre>\n<\/li>\n<\/ol>\n<h2 id=\"session\">2. Establish a session<\/h2>\n<p>The Mobile SDK has to communicate in a secure way with the plataforma de pagamentos da Adyen. For more information, see <a href=\"\/pt\/point-of-sale\/mobile-android\/understand#session\">Communication session<\/a>. <\/p>\n<p>To authenticate your server-to-server API request for establishing a communication session, you need to have an Adyen <a href=\"\/pt\/development-resources\/api-credentials\">API credential<\/a> in your <a href=\"https:\/\/ca-test.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">test Customer Area<\/a>. This credential must have a <a href=\"\/pt\/development-resources\/client-side-authentication\">client key<\/a> and an <a href=\"\/pt\/development-resources\/api-credentials#generate-api-key\">API key<\/a> with the following <a href=\"\/pt\/development-resources\/api-credentials#api-permissions\">role<\/a>:<\/p>\n<ul>\n<li><strong>Checkout webservice role<\/strong>. This role is assigned by default when the API key is created.<\/li>\n<\/ul><p>To add a client key to an existing API credential, create a client key as follows:<\/p>\n<ol>\n<li>Log in to your <a href=\"https:\/\/ca-test.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Customer Area<\/a>.<\/li>\n<li>Go to <strong>Developers<\/strong> &gt; <strong>API credentials<\/strong>, and select the credential username for your integration, for example <strong>ws@Company.[YourCompanyAccount]<\/strong>.<\/li>\n<li>Under <strong>Client settings<\/strong> &gt; <strong>Authentication<\/strong> select the <strong>Client key<\/strong> tab.<\/li>\n<li>Select <strong>Generate client key<\/strong>.<\/li>\n<li>\n<p>Select <strong>Save changes<\/strong>.<\/p>\n<div class=\"sc-notice info\"><div>\n<p>The client key is part of the setup but is not used later on. Therefore, you do not need to specify allowed origins, and you do not need to save the client key in your system.<\/p>\n<\/div><\/div>\n<\/li>\n<\/ol>\n<p>To let your backend establish a session, use the regular endpoint, or the dedicated endpoint for <a href=\"\/pt\/get-started-with-adyen\/adyen-glossary#payment-facilitator-payfac\" target=\"_blank\">payment facilitators<\/a>.<\/p>\n<ul>\n<li>Regular endpoint:  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/possdk\/latest\/post\/sessions\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">\/checkout\/possdk\/v68\/sessions<\/a><\/li>\n<li>Payment facilitator endpoint: <code>\/softposconfig\/v3\/auth\/certificate<\/code><\/li>\n<\/ul>\n\n<div id=\"tabUkVrD\">\n    <div data-component-wrapper=\"tabs\">\n        <tabs\n                        :items=\"[{&quot;title&quot;:&quot;Regular endpoint&quot;,&quot;content&quot;:&quot;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;From your backend, make a POST  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/possdk\\\/latest\\\/post\\\/sessions\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/checkout\\\/possdk\\\/v68\\\/sessions&lt;\\\/a&gt; request, specifying:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Parameter&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Required&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt; &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/possdk\\\/latest\\\/post\\\/sessions#request-merchantAccount\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;merchantAccount&lt;\\\/a&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The unique identifier of your &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/design-your-integration\\\/determine-account-structure#request-merchant-accounts\\&quot;&gt;merchant account&lt;\\\/a&gt;.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt; &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/possdk\\\/latest\\\/post\\\/sessions#request-setupToken\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;setupToken&lt;\\\/a&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The setup token provided by the Mobile SDK through the   implementation of &lt;a href=\\&quot;#enable-transactions\\&quot;&gt;\\n  &lt;code&gt;AuthenticationProvider&lt;\\\/code&gt;\\n&lt;\\\/a&gt; .&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt; &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/possdk\\\/latest\\\/post\\\/sessions#request-store\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;store&lt;\\\/a&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The reference of the &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/design-your-integration\\\/determine-account-structure#create-stores\\&quot;&gt;store&lt;\\\/a&gt; that you want to process payments for. Do not include this parameter if your &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/design-your-integration\\\/determine-account-structure#determine-account-structure\\&quot;&gt;account structure&lt;\\\/a&gt; uses merchant accounts as stores.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;\\\/sessions request&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=\\&quot;[{&amp;quot;language&amp;quot;:&amp;quot;bash&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;curl https:\\\\\\\/\\\\\\\/checkout-test.adyen.com\\\\\\\/checkout\\\\\\\/possdk\\\\\\\/v68\\\\\\\/sessions \\\\\\\\\\\\n-H &#039;content-type: application\\\\\\\/json&#039; \\\\\\\\\\\\n-H &#039;x-API-key: ADYEN_API_KEY&#039; \\\\\\\\\\\\n-X POST \\\\\\\\\\\\n-d &#039;{\\\\n    \\\\&amp;quot;merchantAccount\\\\&amp;quot;: \\\\&amp;quot;YOUR_MERCHANT_ACCOUNT\\\\&amp;quot;,\\\\n    \\\\&amp;quot;setupToken\\\\&amp;quot;: \\\\&amp;quot;SETUP_TOKEN\\\\&amp;quot;,\\\\n    \\\\&amp;quot;store\\\\&amp;quot;: \\\\&amp;quot;YOUR_STORE_REFERENCE\\\\&amp;quot;\\\\n}&#039;&amp;quot;}]\\&quot; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;When you receive the response:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Check that you get a &lt;strong&gt;201 Created&lt;\\\/strong&gt; HTTP status code.&lt;\\\/li&gt;\\n&lt;li&gt;Return the  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/possdk\\\/latest\\\/post\\\/sessions#responses-201-sdkData\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;sdkData&lt;\\\/a&gt; to your POS app.&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;If you create the Terminal API request on your backend, save the  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/possdk\\\/latest\\\/post\\\/sessions#responses-201-installationId\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;installationId&lt;\\\/a&gt; and use this as the &lt;code&gt;POIID&lt;\\\/code&gt; in the &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/design-your-integration\\\/terminal-api#request-message-header\\&quot;&gt;\\n  &lt;code&gt;MessageHeader&lt;\\\/code&gt;\\n&lt;\\\/a&gt; of the payment request.&lt;\\\/p&gt;\\n&lt;!-- list-separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;\\\/sessions response&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=&#039;[{\\&quot;language\\&quot;:\\&quot;json\\&quot;,\\&quot;tabTitle\\&quot;:\\&quot;\\&quot;,\\&quot;content\\&quot;:\\&quot;{\\\\n    \\\\\\&quot;id\\\\\\&quot;: \\\\\\&quot;APP_SESSION_ID\\\\\\&quot;,\\\\n    \\\\\\&quot;installationId\\\\\\&quot;: \\\\\\&quot;INSTALLATION_ID\\\\\\&quot;,\\\\n    \\\\\\&quot;merchantAccount\\\\\\&quot;: \\\\\\&quot;YOUR_MERCHANT_ACCOUNT\\\\\\&quot;,\\\\n    \\\\\\&quot;store\\\\\\&quot;: \\\\\\&quot;YOUR_STORE_ID\\\\\\&quot;,\\\\n    \\\\\\&quot;sdkData\\\\\\&quot;: \\\\\\&quot;SDK_DATA_BLOB\\\\\\&quot;\\\\n}\\&quot;}]&#039; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:&quot;regular_endpoint_0_1&quot;,&quot;relation&quot;:&quot;&quot;},{&quot;title&quot;:&quot;Payment facilitator endpoint&quot;,&quot;content&quot;:&quot;\\n&lt;p&gt;If you are a payment facilitator, card schemes need to receive certain data about your sub-merchant with each transaction. That is because your sub-merchant is considered the Merchant of Record when a transaction is facilitated by you.&lt;\\\/p&gt;\\n&lt;p&gt;Adyen automatically adds certain sub-merchant data to transactions that you facilitate. The remaining data must be supplied by you when you establish a communication session.&lt;\\\/p&gt;\\n&lt;div class=\\&quot;notices red\\&quot;&gt;\\n&lt;p&gt;You must &lt;strong&gt;not&lt;\\\/strong&gt; submit sub-merchant data in your Terminal API requests.&lt;\\\/p&gt;\\n&lt;\\\/div&gt;\\n&lt;h4 id=\\&quot;endpoints-to-use\\&quot;&gt;Endpoints to use&lt;\\\/h4&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Test endpoint: &lt;code&gt;https:\\\/\\\/softposconfig-test.adyen.com\\\/softposconfig\\\/v3\\\/auth\\\/certificate&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;li&gt;Regional live endpoints:\\n&lt;ul&gt;\\n&lt;li&gt;Australia: &lt;code&gt;https:\\\/\\\/softposconfig-live-au.adyen.com\\\/softposconfig\\\/v3\\\/auth\\\/certificate&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;li&gt;Asia Pacific South East: &lt;code&gt;https:\\\/\\\/softposconfig-live-apse.adyen.com\\\/softposconfig\\\/v3\\\/auth\\\/certificate&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;li&gt;Europe: &lt;code&gt;https:\\\/\\\/softposconfig-live.adyen.com\\\/softposconfig\\\/v3\\\/auth\\\/certificate&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;li&gt;North East Asia: &lt;code&gt;https:\\\/\\\/softposconfig-live-nea.adyen.com\\\/softposconfig\\\/v3\\\/auth\\\/certificate&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;li&gt;United States: &lt;code&gt;https:\\\/\\\/softposconfig-live-us.adyen.com\\\/softposconfig\\\/v3\\\/auth\\\/certificate&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;h4&gt;Request and response&lt;\\\/h4&gt;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;From your backend, make a POST request to the applicable &lt;code&gt;\\\/softposconfig\\\/v3\\\/auth\\\/certificate&lt;\\\/code&gt; &lt;a href=\\&quot;#endpoints-to-use\\&quot;&gt;endpoint&lt;\\\/a&gt;, specifying:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Parameter&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Required&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;merchantAccount&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The unique identifier of your &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/design-your-integration\\\/determine-account-structure#request-merchant-accounts\\&quot;&gt;merchant account&lt;\\\/a&gt;.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;setupToken&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The setup token provided by the Mobile SDK through the   implementation of &lt;a href=\\&quot;#enable-transactions\\&quot;&gt;\\n  &lt;code&gt;AuthenticationProvider&lt;\\\/code&gt;\\n&lt;\\\/a&gt; .&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;subMerchantData&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;An object with the details of the sub-merchant. See the next table for details.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;p&gt;The &lt;code&gt;subMerchantData&lt;\\\/code&gt; object includes the following parameters:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Parameter&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Required&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;id&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;You unique identifier of the sub-merchant.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;name&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The name of the sub-merchant.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;mcc&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The sub-merchant&#039;s four-digit Merchant Category Code (MCC). This parameter is used to correctly route the transaction.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;street&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The street name and house number of the sub-merchant&#039;s address.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;city&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The city of the sub-merchant&#039;s address.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;postalCode&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The postal code of the sub-merchant&#039;s address, without dashes.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;country&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The country\\\/region of the sub-merchant&#039;s address, specified as the three-letter country code in &lt;a href=\\&quot;https:\\\/\\\/en.wikipedia.org\\\/wiki\\\/ISO_3166-1_alpha-3\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot; class=\\&quot;external-link no-image\\&quot;&gt;ISO 3166-1 alpha-3&lt;\\\/a&gt; format.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;state&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The state code of the sub-merchant&#039;s address, if applicable for the country or region.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;taxId&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The tax ID of the sub-merchant. Required only in Brazil and for Cartes Bancaires in France. &lt;br&gt; For Brazil, this is the 11-digit CPF or 14-digit CNPJ. &lt;br&gt; For France, this is the SIRET, with a maximum of 14 digits.&lt;\\\/td&gt;\\n&lt;td&gt;&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;email&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The email address of the sub-merchant. Required for American Express.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;phoneNumber&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The phone number of the sub-merchant. Required for American Express.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;\\\/certificate request&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=\\&quot;[{&amp;quot;language&amp;quot;:&amp;quot;bash&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;curl https:\\\\\\\/\\\\\\\/softposconfig-test.adyen.com\\\\\\\/softposconfig\\\\\\\/v3\\\\\\\/auth\\\\\\\/certificate \\\\\\\\\\\\n-H &#039;content-type: application\\\\\\\/json&#039; \\\\\\\\\\\\n-H &#039;x-API-key: ADYEN_API_KEY&#039; \\\\\\\\\\\\n-X POST \\\\\\\\\\\\n-d &#039;{\\\\n    \\\\&amp;quot;merchantAccount\\\\&amp;quot;: \\\\&amp;quot;YOUR_MERCHANT_ACCOUNT\\\\&amp;quot;,\\\\n    \\\\&amp;quot;setupToken\\\\&amp;quot;: \\\\&amp;quot;SETUP_TOKEN\\\\&amp;quot;,\\\\n    \\\\&amp;quot;subMerchantData\\\\&amp;quot;: {\\\\n        \\\\&amp;quot;id\\\\&amp;quot;: \\\\&amp;quot;123456\\\\&amp;quot;,\\\\n        \\\\&amp;quot;name\\\\&amp;quot;: \\\\&amp;quot;Test Merchant\\\\&amp;quot;,\\\\n        \\\\&amp;quot;mcc\\\\&amp;quot;: \\\\&amp;quot;5734\\\\&amp;quot;,\\\\n        \\\\&amp;quot;street\\\\&amp;quot;: \\\\&amp;quot;123 Sample Street\\\\&amp;quot;,\\\\n        \\\\&amp;quot;city\\\\&amp;quot;: \\\\&amp;quot;San Francisco\\\\&amp;quot;,\\\\n        \\\\&amp;quot;state\\\\&amp;quot;: \\\\&amp;quot;CA\\\\&amp;quot;,\\\\n        \\\\&amp;quot;postalCode\\\\&amp;quot;: \\\\&amp;quot;94107\\\\&amp;quot;,\\\\n        \\\\&amp;quot;country\\\\&amp;quot;: \\\\&amp;quot;USA\\\\&amp;quot;,\\\\n        \\\\&amp;quot;taxId\\\\&amp;quot;: \\\\&amp;quot;TAX123456\\\\&amp;quot;,\\\\n        \\\\&amp;quot;displayName\\\\&amp;quot;: \\\\&amp;quot;SF Computer Software\\\\&amp;quot;,\\\\n        \\\\&amp;quot;email\\\\&amp;quot;: \\\\&amp;quot;test-merchant@example.com\\\\&amp;quot;,\\\\n        \\\\&amp;quot;phoneNumber\\\\&amp;quot;: \\\\&amp;quot;+14151234567\\\\&amp;quot;\\\\n    }\\\\n}&#039;&amp;quot;}]\\&quot; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;When you receive the response:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Check that you get a &lt;strong&gt;201 Created&lt;\\\/strong&gt; HTTP status code.&lt;\\\/li&gt;\\n&lt;li&gt;Return the &lt;code&gt;sdkData&lt;\\\/code&gt; to your POS app.&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;If you create the Terminal API request on your backend, save the &lt;code&gt;installationId&lt;\\\/code&gt; and use this as the &lt;code&gt;POIID&lt;\\\/code&gt; in the &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/design-your-integration\\\/terminal-api#request-message-header\\&quot;&gt;\\n  &lt;code&gt;MessageHeader&lt;\\\/code&gt;\\n&lt;\\\/a&gt; of the payment request.&lt;\\\/p&gt;\\n&lt;!-- list-separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;Successful \\\/certificate response&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=&#039;[{\\&quot;language\\&quot;:\\&quot;json\\&quot;,\\&quot;tabTitle\\&quot;:\\&quot;\\&quot;,\\&quot;content\\&quot;:\\&quot;{\\\\n    \\\\\\&quot;id\\\\\\&quot;: \\\\\\&quot;APP_SESSION_ID\\\\\\&quot;,\\\\n    \\\\\\&quot;installationId\\\\\\&quot;: \\\\\\&quot;INSTALLATION_ID\\\\\\&quot;,\\\\n    \\\\\\&quot;merchantAccount\\\\\\&quot;: \\\\\\&quot;YOUR_MERCHANT_ACCOUNT\\\\\\&quot;,\\\\n    \\\\\\&quot;store\\\\\\&quot;: \\\\\\&quot;YOUR_STORE_ID\\\\\\&quot;,\\\\n    \\\\\\&quot;sdkData\\\\\\&quot;: \\\\\\&quot;SDK_DATA_BLOB\\\\\\&quot;\\\\n}\\&quot;}]&#039; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;p&gt;If you receive a response with an error message similar to the following, ask our &lt;a href=\\&quot;https:\\\/\\\/ca-test.adyen.com\\\/ca\\\/ca\\\/contactUs\\\/support.shtml?form=other\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot; class=\\&quot;external-link no-image\\&quot;&gt;Support Team&lt;\\\/a&gt; to configure the MCC that you specified in the request.&lt;\\\/p&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;\\\/certificate error message&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=&#039;[{\\&quot;language\\&quot;:\\&quot;raw\\&quot;,\\&quot;tabTitle\\&quot;:\\&quot;\\&quot;,\\&quot;content\\&quot;:\\&quot;Refused (905_3 Could not find an acquirer account for the provided currency (USD).)\\&quot;}]&#039; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:&quot;payment_facilitator_endpoint_1_2&quot;,&quot;relation&quot;:&quot;&quot;}]\"\n            :should-update-when-url-changes='false'>\n        <\/tabs>\n    <\/div>\n<\/div>\n\n<h2 id=\"enable-transactions\">3. Enable transactions<\/h2>\n<p>To enable the payments functionality of the Mobile SDK for Android, add code to your Android POS app:<\/p>\n<ol>\n<li>\n<p>Implement the <code>AuthenticationProvider<\/code> interface. Note that you need to extract the  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/possdk\/latest\/post\/sessions#responses-201-sdkData\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">sdkData<\/a> from the server response and create an <code>AuthenticationResponse<\/code> object with <code>sdkData<\/code> in the constructor. Below is an example of how you could do that, assuming your project uses OkHttp.<\/p>\n<pre><code class=\"language-kotlin\">class MyAuthenticationProvider : AuthenticationProvider() {\n\n    override suspend fun authenticate(setupToken: String): Result&lt;AuthenticationResponse&gt; {\n\n        \/\/ Make a call to your backend to trigger a `\/checkout\/possdk\/v68\/sessions` request, specifying the `setupToken` provided by the SDK\n\n        val client = OkHttpClient()\n        val request = Request.Builder()\n            .url(\"ADDRESS_OF_YOUR_BACKEND_API\")\n            .build()\n\n        client.newCall(request).execute().use { response -&gt;\n            response.body?.let {\n                \/\/ parse your own back-end response and return AuthenticationResponse\n                \/\/...\n                return Result.success(AuthenticationResponse(sdkData))\n            }\n        }\n    }\n}<\/code><\/pre>\n<\/li>\n<li>\n<p>Implement the <code>MerchantAuthenticationService<\/code> abstract class: in your implementation, provide an instance of your <code>AuthenticationProvider<\/code> from the previous step. If you use Dagger2\/Hilt dependency injection, below is an example of how you could do this:<\/p>\n<pre><code class=\"language-kotlin\">class MyAuthenticationService : MerchantAuthenticationService() {\n\n    @Inject\n    override lateinit var authenticationProvider: AuthenticationProvider\n}<\/code><\/pre>\n<\/li>\n<li>\n<p>Add the service to your POS app's <code>AndroidManifest.xml<\/code> file.<\/p>\n<pre><code class=\"language-xml\"> &lt;service android:name=\".MyAuthenticationService\" \/&gt;<\/code><\/pre>\n<\/li>\n<li>\n<p>Make sure that the <code>MerchantAuthenticationService<\/code> can provide new <code>sdkData<\/code> at any time.<br \/>\nIf there is no session or the session has expired, the service is called using the <code>MerchantAuthenticationService.authenticate(setupToken)<\/code> callback. Using the provided <code>setupToken<\/code> you need to get the <code>sdkData<\/code> through your backend and return it. For instructions, see <a href=\"#session\">Establish a session<\/a>.<\/p>\n<div class=\"notices green\">\n<p>The Adyen POS Mobile SDK detects the <code>MerchantAuthenticationService<\/code> automatically. If the SDK fails to detect the service, an error will occur when SDK methods are called. To resolve this, you can manually set the service using <code>InPersonPayments.setAuthenticationServiceClass()<\/code>.<\/p>\n<\/div>\n<\/li>\n<\/ol>\n<h3>Manage automatic initialization<\/h3>\n<p>The  <a href=\"#enable-transactions\">initializes automatically<\/a>, using the <a href=\"https:\/\/developer.android.com\/topic\/libraries\/app-startup\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Android App Startup library<\/a>. If you prefer to manually initialize the , add the following code to the POS app's <code>AndroidManifest.xml<\/code> file to disable the .<\/p>\n<pre><code class=\"language-kotlin\"> &lt;provider\n     android:name=\"androidx.startup.InitializationProvider\"\n     android:authorities=\"${applicationId}.androidx-startup\"\n     android:exported=\"false\"\n     tools:node=\"merge\"&gt;\n     &lt;meta-data android:name=\"com.adyen.ipp.api.InPersonPaymentsInitializer\"\n               tools:node=\"remove\" \/&gt;\n &lt;\/provider&gt;<\/code><\/pre>\n<p>To manually initialize that component at a later point, add the following code to the POS app.<\/p>\n<p>For  version 2.6.0 or later:<\/p>\n<p>Since the SDK requires the application to be in the foreground to bind to the service, you need to trigger initialization when your main Activity is visible. Use <code>repeatOnLifecycle<\/code> to ensure that the initialization runs when the Activity is in the <code>RESUMED<\/code> state. <\/p>\n<pre><code class=\"language-kotlin\">override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n\n    lifecycleScope.launch {\n        \/\/ Suspend execution until the Activity is RESUMED\n        repeatOnLifecycle(Lifecycle.State.RESUMED) {\n            val state = InPersonPaymentsTools.initializeManually(this@MainActivity)\n\n            if (state is InitializationState.SuccessfulInitialization) {\n                \/\/ SDK is ready\n            } else {\n                \/\/ Handle failure\n            }\n        }\n    }\n}<\/code><\/pre>\n<p>For  versions earlier than version 2.6.0:<\/p>\n<pre><code class=\"language-kotlin\">AppInitializer.getInstance(this)\n    .initializeComponent(InPersonPaymentsInitializer::class.java)<\/code><\/pre>\n<h3>Initialization status check<\/h3>\n<p>To check the status of the SDK initialization, you can use one of the following options.<\/p>\n<p>For  version 2.6.0 or later:<\/p>\n<pre><code class=\"language-kotlin\">when (val state = InPersonPaymentsTools.getInitializationState()){\n    InitializationState.SuccessfulInitialization -&gt; {\n        \/\/ SDK is ready. You can now safely proceed.\n    }\n\n    is InitializationState.FailedInitialization -&gt; {\n        \/\/ Handle initialization failure. Log errors or notify the user.\n        Log.e(\"MyApp\", \"SDK initialization failed: ${state.failureReasons}\")\n    }\n\n    else -&gt; Unit\n}<\/code><\/pre>\n<p>or for  versions earlier than version 2.6.0 if you need more precise control over the state flow:<\/p>\n<pre><code class=\"language-kotlin\">InPersonPayments.initialized\n    .filter { it == InitializationState.SuccessfulInitialization } \/\/ Wait until it is true.\n    .take(1)       \/\/ Take only one item.\n    .collect { ready -&gt;\n        if (ready) {\n            val id = InPersonPayments.getInstallationId()\n            \/\/...\n        }\n    }<\/code><\/pre>\n<h3>Manage POS app dependency initialization<\/h3>\n<p>The code that you add to the <code>Application.onCreate()<\/code> method is executed for all processes. In some cases, it can be beneficial to skip the re-execution of the code, for example the initialization of your dependency graph or analytics libraries.<\/p>\n<p>The following method evaluates specific conditions and returns a boolean value that indicates whether the initialization should be skipped.<\/p>\n<pre><code class=\"language-kotlin\">if (InPersonPaymentsTools.shouldSkipAppInitialize(context)) {\n    \/\/ Perform actions when initialization should be skipped\n} else {\n    \/\/ Proceed with application initialization\n}<\/code><\/pre>\n<p>Additionally, you can use the following functions:<\/p>\n<ul>\n<li>\n<p><code>suspend InPersonPaymentsTools.getInitializationState()<\/code>: this function observes the initialization state of the SDK and pauses the calling coroutine until the SDK initialization finishes and reaches a success or failure state. You can use this suspend function if an action in your app depends on the SDK being fully initialized.<\/p>\n<\/li>\n<li>\n<p><code>suspend InPersonPaymentsTools.initializeManually()<\/code>: this function triggers initialization of the SDK and waits for the initialization to finish.<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"use-warm-up\">4. Use the warm-up function<\/h2>\n<p>To speed up initiating transactions, you can use the warm-up function. This function checks for a session, configuration changes, and security checks if needed.<\/p>\n<p>As a best practice, call the warm-up function after the SDK has initialized:<\/p>\n<ul>\n<li>When the POS app starts.<\/li>\n<li>When the POS app returns to the foreground.<\/li>\n<\/ul>\n<p>To call the warm-up function:<\/p>\n<pre><code class=\"language-kotlin\">InPersonPayments.warmUp()<\/code><\/pre>\n<h2>5. (Optional) Avoid delays<\/h2>\n<p>You can avoid delays and speed up the transaction by preparing the card reader outside a transaction flow with configuration and security checks.<\/p>\n<p>When you start a transaction, the Mobile SDK connects with the card reader to check the reader's configuration. If the configuration is not up to date, the Mobile SDK sends the latest configuration files to the reader. This can take up to to 30 seconds. Additionally, the Mobile SDK performs a security check every 24 hours. To avoid a delay during the transaction flow, you can prepare the card reader by running these checks outside the transaction flow.<\/p>\n<p>It is possible to start a transaction while the card reader preparation is running. There can be a short delay during the transaction while any remaining checks and configuration updates are completed.<\/p>\n<p>We recommend preparing the device for transaction every 24 hours or when the configuration has changed.<\/p>\n<p>To prepare the device outside a transaction flow, call the <span translate=\"no\"><strong>DeviceManager<\/strong><\/span> <code>prepareDeviceForTransaction<\/code> function  as follows, where the <code>device<\/code> is the card reader to prepare.<\/p>\n<pre><code class=\"language-kotlin\">\/\/ Get the DeviceManager\n        val deviceManager = AdyenCardReaders.getInstance(context).deviceManager\n        \/\/ Listen for when a device is connected\n        deviceManager.connectionState.collect { connectionState -&gt;\n            if(connectionState is CardReaderState.Connected) {\n                val device = connectionState.cardReaderInfo\n                \/\/ Prepare the connected device\n                deviceManager.prepareDeviceForTransaction(device)\n            }\n        }<\/code><\/pre>\n<h2>6. Manage the Device Manager UI<\/h2>\n<p>To use the card reader, operators need to:<\/p>\n<ul>\n<li>Connect the mobile device with the card reader through Bluetooth pairing or through USB using a dock or direct USB (if the Android device supports USB host mode).<\/li>\n<li>View an overview of card readers. For example, to switch to a different card reader.<\/li>\n<li>View details of the card reader they are using. For example, to check the battery charge level.<\/li>\n<li>Update the firmware of the card reader or the dock they are using.<\/li>\n<\/ul>\n<p>To handle these tasks, the SDK provides Device Manager functions that enable you to either:<\/p>\n<ul>\n<li>Use the built-in UI.<\/li>\n<li>Build a custom UI.<\/li>\n<\/ul>\n\n<div id=\"tabkQitv\">\n    <div data-component-wrapper=\"tabs\">\n        <tabs\n                        :items=\"[{&quot;title&quot;:&quot;Use the built-in UI&quot;,&quot;content&quot;:&quot;\\n&lt;p&gt;To use the built-in UI, you only need to:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;\\n&lt;p&gt;&lt;strong&gt;Launch the Device Manager&lt;\\\/strong&gt;.&lt;br \\\/&gt;\\nThis automatically takes care of all screens and flows that end users need. For a preview, see:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#ui-for-card-reader-operations\\&quot;&gt;UI for card reader operations&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#bt-pairing\\&quot;&gt;Bluetooth pairing&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#updating-card-reader\\&quot;&gt;Updating the card reader firmware&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#connecting-usb-dock\\&quot;&gt;Connecting through a dock&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#updating-usb-dock\\&quot;&gt;Updating the dock firmware&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Recommended: &lt;strong&gt;avoid delays when connected through Bluetooth&lt;\\\/strong&gt;.&lt;br \\\/&gt;\\nWhen connected through Bluetooth, the card reader enters sleep mode after five minutes of inactivity. When you start a transaction after the reader has gone to sleep, there is a slight delay while the mobile device reconnects to the last connected reader.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;&lt;strong&gt;Alert users to available firmware updates&lt;\\\/strong&gt;.&lt;br \\\/&gt;\\nThe built-in UI automatically signals that a firmware update is available. In practice however, end users often need an extra reminder. For a secure transaction flow, it is very important that end users update the devices. We therefore strongly recommend that you implement a command to check for firmware updates and create a UI to alert end users and direct them to the built-in screen for performing the update.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;Proceed as follows:&lt;\\\/p&gt;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;If you disabled automatic initialization of the Mobile SDK, &lt;a href=\\&quot;#manage-automatic-initialization\\&quot;&gt;initialize the SDK manually&lt;\\\/a&gt;. If you are unsure of the status of the SDK initialization you can run a &lt;a href=\\&quot;#initialization-status-check\\&quot;&gt;status check&lt;\\\/a&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;To use the device management screens built into the Mobile SDK for Android, call the following code corresponding to your launching method.&lt;\\\/p&gt;\\n&lt;pre&gt;&lt;code class=\\&quot;language-kotlin\\&quot;&gt;\\\/\\\/ Launching from an Activity\\nDeviceManagementActivity.start(this)\\n\\n\\\/\\\/ Launching from a Fragment\\nDeviceManagementActivity.start(requireActivity())\\n\\n\\\/\\\/ Launching from Compose\\nval context = LocalContext.current\\n(context as? Activity)?.let { activity -&amp;gt;\\n   DeviceManagementActivity.start(activity)\\n}&lt;\\\/code&gt;&lt;\\\/pre&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Avoid delays when connected through Bluetooth by taking either of the following measures:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Before starting the transaction, wake up the card reader by calling the &lt;code&gt;DeviceManager.connect(cardReader: CardReader)&lt;\\\/code&gt; function.&lt;\\\/li&gt;\\n&lt;li&gt;Regularly refresh the connection between the mobile device and the card reader by implementing a timer that calls the  &lt;code&gt;DeviceManager.connect(cardReader: CardReader)&lt;\\\/code&gt; function every couple of minutes. However, implementing a timer can significantly decrease the battery life of the card reader.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;div class=\\&quot;notices green\\&quot;&gt;\\n&lt;p&gt;When connected through USB, the card reader is always ready for use without delay. There is no need to reconnect to the card reader before initiating a transaction.&lt;\\\/p&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Regularly check for firmware updates for the card reader and, if used, the dock:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;\\n&lt;p&gt;To check for card reader updates, call the &lt;code&gt;DeviceManager.firmwareUpdateState()&lt;\\\/code&gt; function. The result returns the following possible values:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Value&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;NoneAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;There are no new updates available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;DeviceUpdateAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;A device firmware update is available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;BluetoothUpdateAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;A Bluetooth firmware update is available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;MultipleUpdatesAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Bluetooth and device firmware updates are available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;p&gt;If a new update is available, the result also returns the date by which transactions will be refused if the card reader is not updated to this firmware version. When connected through USB, Bluetooth updates cannot be completed and the SDK does not return information about available Bluetooth updates.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;To check for dock updates, call the &lt;code&gt;DeviceManager.dockFirmwareUpdateSummary()&lt;\\\/code&gt; function. If a new update is available, the result returns &lt;code&gt;AvailableDockFirmwareUpdate&lt;\\\/code&gt; and the date by which transactions will be refused if the dock is not updated to this firmware version. If there is no new update, a null value is returned.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Create a UI to prompt end users to update their devices, redirecting them to the built-in UI for performing the update. This is in addition to the built-in screens that alert to available updates.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:&quot;use_the_built-in_ui_0_1&quot;,&quot;relation&quot;:&quot;&quot;},{&quot;title&quot;:&quot;Build a custom UI&quot;,&quot;content&quot;:&quot;\\n&lt;div class=\\&quot;sc-notice info\\&quot;&gt;&lt;div&gt;\\n&lt;p&gt;If you disabled automatic initialization of the Mobile SDK, you need to &lt;a href=\\&quot;#manage-automatic-initialization\\&quot;&gt;initialize the SDK manually&lt;\\\/a&gt;.&lt;\\\/p&gt;\\n&lt;\\\/div&gt;&lt;\\\/div&gt;\\n&lt;p&gt;If you intend to build your own UI for device management, use the &lt;code&gt;DeviceManager&lt;\\\/code&gt; interface to obtain all the necessary information.&lt;\\\/p&gt;\\n&lt;pre&gt;&lt;code class=\\&quot;language-kotlin\\&quot;&gt;val deviceManager = AdyenCardReaders.getInstance(context).deviceManager&lt;\\\/code&gt;&lt;\\\/pre&gt;\\n&lt;p&gt;For an overview, see the &lt;a href=\\&quot;#devicemanager-functions\\&quot;&gt;List of DeviceManager functions&lt;\\\/a&gt;. The next sections provide information about the Device Manager functions you can use when building a UI for:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;a href=\\&quot;#bt-pairing\\&quot;&gt;Bluetooth pairing&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;a href=\\&quot;#updating-card-reader\\&quot;&gt;Updating the card reader firmware&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;a href=\\&quot;#connecting-usb-dock\\&quot;&gt;Connecting through USB using a dock&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;a href=\\&quot;#updating-usb-dock\\&quot;&gt;Updating the dock firmware&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;h3 id=\\&quot;bt-pairing\\&quot;&gt;Bluetooth pairing&lt;\\\/h3&gt;\\n&lt;p&gt;To build a UI for the Bluetooth pairing flow:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Get a list of nearby card readers by calling the &lt;code&gt;DeviceManager.startBluetoothDiscovery()&lt;\\\/code&gt; function.&lt;\\\/li&gt;\\n&lt;li&gt;Connect to a card reader by calling the &lt;code&gt;DeviceManager.connect(cardReader: CardReader)&lt;\\\/code&gt; function.&lt;\\\/li&gt;\\n&lt;li&gt;Check if the Bluetooth pairing succeeded by listening to the &lt;code&gt;DeviceManager.connectionState&lt;\\\/code&gt; flow. If the state changes to &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;CardReaderState.Connected&lt;\\\/strong&gt;&lt;\\\/span&gt;, the reader was paired successfully.&lt;\\\/li&gt;\\n&lt;li&gt;To disconnect from a card reader, call the &lt;code&gt;disconnect()&lt;\\\/code&gt; function.&lt;\\\/li&gt;\\n&lt;li&gt;As an example, &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#bt-pairing\\&quot;&gt;see the built-in UI screens&lt;\\\/a&gt;.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;When connected through Bluetooth, the card reader enters sleep mode after five minutes of inactivity. When you start a transaction after the reader has gone to sleep, there is a slight delay while the mobile device reconnects to the last connected reader. To avoid this delay, you can take either of the following measures:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Before starting the transaction, wake up the card reader by calling the &lt;code&gt;DeviceManager.connect(cardReader: CardReader)&lt;\\\/code&gt; function.&lt;\\\/li&gt;\\n&lt;li&gt;Regularly refresh the connection between the mobile device and the card reader by implementing a timer that calls the &lt;code&gt;DeviceManager.connect(cardReader: CardReader)&lt;\\\/code&gt; function every couple of minutes. However, implementing a timer can significantly decrease the battery life of the card reader.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;h3 id=\\&quot;updating-card-reader\\&quot;&gt;Updating the card reader firmware&lt;\\\/h3&gt;\\n&lt;div class=\\&quot;notices yellow\\&quot;&gt;\\n&lt;p&gt;You must check for new firmware updates regularly, and provide a way to update the card reader to the latest version.&lt;\\\/p&gt;\\n&lt;\\\/div&gt;\\n&lt;p&gt;Firmware updates for the card reader are critical for secure transactions, and do not happen automatically.&lt;\\\/p&gt;\\n&lt;p&gt;It is required that you build logic into your POS app to:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Check for new firmware updates often. For example, when the app is launched.&lt;\\\/li&gt;\\n&lt;li&gt;Handle the firmware update flow correctly within your POS app.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;Your UI must prompt end users to update the card reader firmware, and inform them about the progress and result of the update process.&lt;\\\/p&gt;\\n&lt;p&gt;To build your UI:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;\\n&lt;p&gt;Check if updates are available by calling the &lt;code&gt;DeviceManager.firmwareUpdateState()&lt;\\\/code&gt; function. The available update can be for the device layer, the application layer, the Bluetooth layer, or multiple layers at the same time. The result returns the following possible values:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Value&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;NoneAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;There are no new updates available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;DeviceUpdateAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;A device firmware update is available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;BluetoothUpdateAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;A Bluetooth firmware update is available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;MultipleUpdatesAvailable&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Bluetooth and device firmware updates are available.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;p&gt;If a new update is available, the result also returns the date by which transactions will be refused if the card reader is not updated to this firmware version. When connected through USB, Bluetooth updates cannot be completed and the SDK does not return information about available Bluetooth updates.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Start the update using the &lt;code&gt;DeviceManager.startFirmwareUpdate()&lt;\\\/code&gt; function.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Listen to the &lt;code&gt;FirmwareUpdatingState&lt;\\\/code&gt; flow to build UI screens showing the progress and result of the update.&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;State&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.Downloading&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The SDK retrieves all necessary files from Adyen.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.UpdatingDevice&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The SDK installs the update on the card reader.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.Applying&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The SDK applies the update. The card reader will reboot and reconnect.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.Finished&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Indicates the process has completed.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Errors that can happen during software updates are:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Error&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;DownloadFailed&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Downloading the firmware update files did not succeed.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;UpdateFailed(needsBluetoothRecovery: Boolean)&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The update was not completed. The variable &lt;code&gt;needsBluetoothRecovery&lt;\\\/code&gt; indicates if the Bluetooth update failed and card reader must be reset before retrying the update.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;p&gt;If the card reader must be reset before retrying the update, your UI should provide the following instructions:&lt;\\\/p&gt;\\n&lt;blockquote&gt;\\n&lt;ol&gt;\\n&lt;li&gt;Power off the reader.&lt;\\\/li&gt;\\n&lt;li&gt;Press and hold the power button until a single loud beep sounds.&lt;\\\/li&gt;\\n&lt;li&gt;Wait for the reader to reset and reboot.&lt;\\\/li&gt;\\n&lt;li&gt;In the Bluetooth settings of the mobile device, select \\&quot;Forget This Device\\&quot;.&lt;\\\/li&gt;\\n&lt;li&gt;Re-pair the reader and retry installing the update.&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&lt;\\\/blockquote&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;As an example, &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#updating-card-reader\\&quot;&gt;see the built-in UI screens&lt;\\\/a&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;h3 id=\\&quot;connecting-usb-dock\\&quot;&gt;Connecting through USB using a dock&lt;\\\/h3&gt;\\n&lt;p&gt;A USB connection is automatically established when the user connects the dock to power, connects the mobile device to the dock using the USB-C cable provided with the card reader, and places the reader in the dock.&lt;\\\/p&gt;\\n&lt;p&gt;Your UI must clearly show the difference between these situations:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;The mobile device is connected to the dock through USB, but no card reader is placed in the dock.&lt;\\\/li&gt;\\n&lt;li&gt;The card reader is placed in the dock, but the mobile device is connected to the card reader through Bluetooth.&lt;\\\/li&gt;\\n&lt;li&gt;The card reader is placed in the dock and the mobile device is connected to the dock and the reader through USB.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;To build your UI for dock connections:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;\\n&lt;p&gt;Connect to a dock by calling the &lt;code&gt;connectToDock(usbAccessory: UsbAccessory)&lt;\\\/code&gt; function.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Check if the connection succeeded by listening to the &lt;code&gt;DeviceManager.dockConnectionState: StateFlow&amp;lt;DockState&amp;gt;&lt;\\\/code&gt; flow. If the state changes to &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;DockState.Connected&lt;\\\/strong&gt;&lt;\\\/span&gt;, the reader and the dock were was connected successfully.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;To refresh the USB connection to the dock, call the &lt;code&gt;refreshConnectionStateForAttachedDock()&lt;\\\/code&gt; function.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;To disconnect from a dock, call the &lt;code&gt;disconnect()&lt;\\\/code&gt; function.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;As an example, &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#connecting-usb-doc\\&quot;&gt;see the built-in UI screens&lt;\\\/a&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;When connected through USB, the card reader is always ready for use without delay. There is no need to reconnect to the card reader before initiating a transaction.&lt;\\\/p&gt;\\n&lt;h3 id=\\&quot;updating-usb-dock\\&quot;&gt;Updating the dock firmware&lt;\\\/h3&gt;\\n&lt;div class=\\&quot;notices yellow\\&quot;&gt;\\n&lt;p&gt;You must check for new firmware updates regularly, and provide a way to update the dock to the latest version.&lt;\\\/p&gt;\\n&lt;\\\/div&gt;\\n&lt;p&gt;Firmware updates for the dock are critical for secure transactions, and do not happen automatically.&lt;\\\/p&gt;\\n&lt;p&gt;It is required that you build logic into your POS app to:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;Check for new firmware updates often. For example, when the app is launched.&lt;\\\/li&gt;\\n&lt;li&gt;Handle the firmware update flow correctly within your POS app.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;Your UI must prompt end users to update the dock firmware, and inform them about the progress and result of the update process.&lt;\\\/p&gt;\\n&lt;p&gt;To build your UI:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;\\n&lt;p&gt;Check if updates are available by calling the &lt;code&gt;DeviceManager.dockFirmwareUpdateSummary()&lt;\\\/code&gt; function. If a new update is available, the result returns &lt;code&gt;AvailableDockFirmwareUpdate&lt;\\\/code&gt; and the date by which transactions will be refused if the dock is not updated to this firmware version. If there is no new update, a null value is returned.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Start the update using the &lt;code&gt;DeviceManager.startDockFirmwareUpdate()&lt;\\\/code&gt; function.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Listen to the &lt;code&gt;FirmwareUpdatingState&lt;\\\/code&gt; flow to build UI screens showing the progress and result of the update.&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;State&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.Downloading&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The SDK retrieves all necessary files from Adyen.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.UpdatingDevice&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The SDK installs the update on the dock.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.Applying&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The SDK applies the update.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;FirmwareUpdatingState.Finished&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Indicates the process has completed.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Errors that can happen during software updates are:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Error&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;DownloadFailed&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Downloading the firmware update files did not succeed.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;As an example, &lt;a href=\\&quot;\\\/pt\\\/point-of-sale\\\/mobile-android\\\/understand#updating-usb-dock\\&quot;&gt;see the built-in UI screens&lt;\\\/a&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;h3 id=\\&quot;devicemanager-functions\\&quot;&gt;List of DeviceManager tools&lt;\\\/h3&gt;\\n&lt;p&gt;&lt;code&gt;DeviceManager&lt;\\\/code&gt; lets you scan for card readers through Bluetooth device discovery, connect and disconnect a card reader, connect and disconnect a USB dock, get information about the currently connected card reader, get information about the currently USB dock, and manage firmware updates.&lt;\\\/p&gt;\\n&lt;p&gt;You can use the following functions:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;DeviceManager tool&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;connectionState: StateFlow&amp;lt;ReaderConnectedState&amp;gt;&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Returns the connection state of the currently connected card reader.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;startBluetoothDiscovery(): Flow&amp;lt;Result&amp;lt;List&amp;lt;DiscoveredDevice&amp;gt;&amp;gt;&amp;gt;&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Starts scanning for nearby card readers. Returns an error if scanning failed.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;stopBluetoothDiscovery()&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Stops scanning for nearby card readers.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;getKnownDevices(): List&amp;lt;CardReaderDevice&amp;gt;&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Returns a list of paired card readers.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;connect(cardReaderDevice: CardReaderDevice)&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Connects to a card reader.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;disconnect()&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Disconnects from the currently connected card reader or USB dock.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;firmwareUpdateSummary(): Result&amp;lt;AvailableFirmwareUpdate&amp;gt;&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Returns information about available firmware updates for the card reader that is currently connected to the mobile device. The result includes: &lt;ul&gt;&lt;li markdown=\\&quot;1\\&quot;&gt;&lt;code&gt;requiresBluetoothConnection&lt;\\\/code&gt;: indicates if a Bluetooth connection is required to update the card reader.&lt;\\\/li&gt; &lt;li markdown=\\&quot;1\\&quot;&gt;&lt;code&gt;requiredDate&lt;\\\/code&gt;: &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;null&lt;\\\/strong&gt;&lt;\\\/span&gt;, or the date by which transactions will be refused if the card reader is not updated to this firmware version.&lt;\\\/li&gt;&lt;\\\/ul&gt;&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;startFirmwareUpdate()&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Implements the available card reader firmware update. Shows an error if the update failed because the card reader was connected through USB and the update required a Bluetooth connection.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;dockConnectionState: StateFlow&amp;lt;DockState&amp;gt;&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Returns the connection state of the currently connected USB dock.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;connectToDock(usbAccessory: UsbAccessory)&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Connects to a USB dock.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;dockFirmwareUpdateSummary(): Result&amp;lt;AvailableDockFirmwareUpdate?&amp;gt;&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Returns information about available firmware updates for the USB Dock that is currently connected to the mobile device. The result includes: &lt;ul&gt;&lt;li markdown=\\&quot;1\\&quot;&gt;&lt;code&gt;requiredDate&lt;\\\/code&gt;: &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;null&lt;\\\/strong&gt;&lt;\\\/span&gt;, or the date by which transactions will be refused if the dock is not updated to this firmware version.&lt;\\\/li&gt;&lt;\\\/ul&gt;&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;startDockFirmwareUpdate()&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Implements the available firmware update for the USB dock.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;code&gt;refreshConnectionStateForAttachedDock()&lt;\\\/code&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;Refreshes the connected and attached status of USB dock.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:&quot;build_a_custom_ui_1_2&quot;,&quot;relation&quot;:&quot;&quot;}]\"\n            :should-update-when-url-changes='false'>\n        <\/tabs>\n    <\/div>\n<\/div>\n\n<h2 id=\"transaction-ui-options\">7. Decide on transaction UI options<\/h2>\n<p>In this step you decide on the options that are available for customizing the transaction user interface.<\/p>\n<p>If you want the UI to appear in dark mode, you need to enable this options in the settings of your mobile device.<\/p>\n<p>When you <a href=\"#payment\">start a transaction<\/a>, you can customize the user interface using <code>merchantUiParameters<\/code> and the optional fields for the following UI options:<\/p>\n<div class=\"accordion-shortcode adl-accordion adl-accordion--max-height-transition\" data-expand=\"true\" data-ignore=\"anchorjs-link\">\n    \n    <div class=\"adl-accordion__item\" style=\"\">\n        <div tabindex=\"0\" role=\"item\" aria-expanded=\"false\" class=\"adl-accordion__header\">\n            <i class=\"adl-accordion__toggle adl-icon-chevron-down\"><\/i>\n            <div class=\"adl-accordion__title-wrapper\" data-accordion=\"#add-a-logo\">\n                                    <h4 class=\"adl-accordion__title\">Add a logo<\/h4>\n                            <\/div>\n        <\/div>\n        <div role=\"region\" class=\"adl-accordion__content\">\n            \n<p>To show a logo on your mobile device during the transaction flow use:<\/p>\n<ul>\n<li>\n<p><code>merchantLogo<\/code>: Format can be SVG (recommended), WEBP, JPEG, or PNG. The logo is shown at 100dp&nbsp;x&nbsp;32dp (width&nbsp;x&nbsp;height) on top of the payment screen. Trim any transparent pixels from the logo asset, to show your logo as large as possible within the available space.<\/p>\n<pre><code class=\"language-kotlin\">(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  merchantLogo = R.drawable.merchant_logo,\n  \/\/ ...\n)<\/code><\/pre>\n<\/li>\n<\/ul>\n\n        <\/div>\n    <\/div>\n<\/div>\n\n<div class=\"accordion-shortcode adl-accordion adl-accordion--max-height-transition\" data-expand=\"true\" data-ignore=\"anchorjs-link\">\n    \n    <div class=\"adl-accordion__item\" style=\"\">\n        <div tabindex=\"0\" role=\"item\" aria-expanded=\"false\" class=\"adl-accordion__header\">\n            <i class=\"adl-accordion__toggle adl-icon-chevron-down\"><\/i>\n            <div class=\"adl-accordion__title-wrapper\" data-accordion=\"#configure-success-screen-duration\">\n                                    <h4 class=\"adl-accordion__title\">Configure success screen duration<\/h4>\n                            <\/div>\n        <\/div>\n        <div role=\"region\" class=\"adl-accordion__content\">\n            \n<p>To specify how long the success screen shows after a successful transaction use: <\/p>\n<ul>\n<li>\n<p><code>autoDismissDelay<\/code>: If not specified, this success screen is dismissed after 4 seconds. You can set a time in milliseconds with a minimum of 0.5&nbsp;seconds (500L) and a maximum of 4&nbsp;seconds (4000L).<\/p>\n<pre><code class=\"language-kotlin\">(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  autoDismissDelay = 3.seconds,\n  \/\/ ...\n)<\/code><\/pre>\n<\/li>\n<\/ul>\n\n        <\/div>\n    <\/div>\n<\/div>\n\n<div class=\"accordion-shortcode adl-accordion adl-accordion--max-height-transition\" data-expand=\"true\" data-ignore=\"anchorjs-link\">\n    \n    <div class=\"adl-accordion__item\" style=\"\">\n        <div tabindex=\"0\" role=\"item\" aria-expanded=\"false\" class=\"adl-accordion__header\">\n            <i class=\"adl-accordion__toggle adl-icon-chevron-down\"><\/i>\n            <div class=\"adl-accordion__title-wrapper\" data-accordion=\"#customize-position-of-the-nfc-tap-indicator\">\n                                    <h4 class=\"adl-accordion__title\">Customize position of the NFC tap indicator<\/h4>\n                            <\/div>\n        <\/div>\n        <div role=\"region\" class=\"adl-accordion__content\">\n            \n<p>By default, the NFC tap indicator is an animation that points at the back of the device. You can customize the position of the NFC tap indicator on your mobile device screen to point at the location of your card reader. Then use<code>CardReaderAnimationType<\/code>. This allows you to show a chevron-type arrow (<code>Simplified<\/code>), pointing in the specified direction. If there is not enough room on the mobile device screen, no chevron-type arrow can be shown. Instead, a tap indicator is shown in the center of the screen. <\/p>\n<ul>\n<li>\n<p>Options for 'Simplified' are: <code>CenterRight<\/code>, or <code>CenterLeft<\/code>. <\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">CenterLeft<\/th>\n<th style=\"text-align: center;\">CenterRight<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: center;\"><img style=\"width: 150px;\" alt=\"\" src=\"\/user\/pages\/reuse\/pos-mobile-sdk\/android-build\/transaction-ui-options\/simplified_centerleft.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<td style=\"text-align: center;\"><img style=\"width: 150px;\" alt=\"\" src=\"\/user\/pages\/reuse\/pos-mobile-sdk\/android-build\/transaction-ui-options\/simplified_centerright.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"language-kotlin\">(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  cardReaderUiParameters = CardReaderUiParameters.create(\n      animation = CardReaderAnimationType.simplified(Position.Center),\n  ),\n  \/\/ ...\n)<\/code><\/pre>\n<\/li>\n<\/ul>\n\n        <\/div>\n    <\/div>\n<\/div>\n\n<h2 id=\"payment\">8. Handle a payment<\/h2>\n<p>In this step you add code to start a transaction with:<\/p>\n<ul>\n<li>A <a href=\"\/pt\/point-of-sale\/design-your-integration\/terminal-api\">Terminal API<\/a> payment request.<\/li>\n<li>\nThe card reader as the payment interface to use. <\/li>\n<\/ul>\n<p>To let the Mobile SDK handle transactions:<\/p>\n<ol>\n<li>\n<p>In your POS app, create a Terminal API payment request with:<\/p>\n<ul>\n<li>\n<p><code>MessageHeader.POIID<\/code>: the installation ID of the SDK.<\/p>\n<ul>\n<li>If you create the Terminal API payment request in your POS app, use <code>InPersonPayments.getInstallationId()<\/code> as the <code>POIID<\/code> in the <a href=\"\/pt\/point-of-sale\/design-your-integration\/terminal-api#request-message-header\">MessageHeader<\/a> of the request.<\/li>\n<li>If you create the Terminal API payment request in the backend, this uses the  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/possdk\/latest\/post\/sessions#responses-201-installationId\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">installationId<\/a> from the <a href=\"#session\"><code>\/checkout\/possdk\/v68\/sessions<\/code> response<\/a>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>The remaining <code>MessageHeader<\/code> parameters and the request body.<\/p>\n<div class=\"sc-notice info\"><div>\n<p>For details, see <a href=\"\/pt\/point-of-sale\/basic-tapi-integration\/make-a-payment\">Make a payment<\/a> and <a href=\"https:\/\/docs.adyen.com\/api-explorer\/terminal-api\/latest\/post\/payment\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">PaymentRequest<\/a>.<\/p>\n<\/div><\/div>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Create an instance of <code>TransactionRequest<\/code> using <code>TransactionRequest.create(nexoRequest)<\/code>, and pass the Terminal API payment request from your POS app or backend.<\/p>\n<pre><code class=\"language-kotlin\">val transactionRequest = TransactionRequest.create(nexoRequest)<\/code><\/pre>\n<\/li>\n<li>\n<p>Get a <code>PaymentInterface<\/code> from <code>InPersonPayments<\/code> using  <code>InPersonPayments.getPaymentInterface(CardReader)<\/code>. <\/p>\n<pre><code class=\"language-kotlin\">val paymentInterface = InPersonPayments.getPaymentInterface(CardReader)<\/code><\/pre>\n<\/li>\n<li>\n<p>Register a listener for the <code>PaymentResult<\/code> and pass the <code>transactionResponse<\/code> to your POS app. This is the Terminal API payment response, including data you can use to generate a receipt.<\/p>\n<pre><code class=\"language-kotlin\">InPersonPayments.registerForPaymentResult(context) { result -&gt;\n  result.fold(\n    onSuccess = { paymentResult: PaymentResult -&gt;\n        \/*\n         * Here is your success case logic, for example:\n         * if (paymentResult.success) \"Payment Successful\" else \"Payment Unsuccessful\"\n         *\/\n    },\n    onFailure = { error: Throwable -&gt;\n        \/*\n         * Here is your failure case logic, for example:\n         * Log.e(\"InPersonPaymentsResult\", \"Payment Failed\", error)\n         *\/\n    },\n)<\/code><\/pre>\n<\/li>\n<li>\n<p>Invoke <code>InPersonPayments.performTransaction()<\/code> with your transaction data, payment launcher, and <a href=\"\/pt\/point-of-sale\/mobile-ios\/build\/card-reader#enable-transactions\">authentication service<\/a>. <\/p>\n<p>Then customize the user interface using <code>merchantUiParameters<\/code> with the <a href=\"#transaction-ui-options\">optional fields that you decided on<\/a> in the previous step. The following example invokes <code>InPersonPayments.performTransaction()<\/code> and includes parameters to add a custom logo and customizing the position of the NFC tap indicator on your mobile device screen:<\/p>\n<pre><code class=\"language-kotlin\">InPersonPayments.performTransaction(\n    context = this@DevAmountEntryActivity,\n    paymentLauncher = paymentLauncher,\n    paymentInterface = result.paymentInterface,\n    transactionRequest = result.transactionRequest,\n    merchantUiParameters = MerchantUiParameters.create(\n        merchantLogo = R.drawable.merchant_logo,\n        tapToPayUiParameters = TapToPayUiParameters.create(\n            animation = TapToPayAnimationType.front(NfcFrontPosition.TopCenter),\n        ),\n        cardReaderUiParameters = CardReaderUiParameters(\n            animation = CardReaderAnimationType.simplified(Position.CenterLeft),\n        ),\n    ),\n)<\/code><\/pre>\n<p>The Mobile SDK checks for a session, starts the transaction, and shows screens on your mobile device to help the customer.<\/p>\n<\/li>\n<\/ol>\n<div class=\"notices green\">\n<p>If the shopper does not present their payment method within 30 seconds, the payment request times out. If that happens, you need to make another payment request.<\/p>\n<\/div>\n<h2 id=\"refund\">9. Handle a refund<\/h2>\n<p>There are two types of refund: <a href=\"#referenced-refund\">referenced<\/a> and <a href=\"#unreferenced-refund\">unreferenced<\/a>. The main difference is that a referenced refund is connected to the original payment, and an unreferenced refund isn't. That makes unreferenced refunds a bit riskier. For an overview of the differences, see <a href=\"\/pt\/point-of-sale\/basic-tapi-integration\/refund-payment\">Refund a payment<\/a>.<\/p>\n<p>Refunds are usually <em>not<\/em> processed synchronously. When you send a request for a referenced or unreferenced refund, the Terminal API response only confirms we received the request. <\/p>\n<p>We inform you about the outcome of the refund asynchronously, through a webhook.<\/p>\n<ul>\n<li>For a referenced refund, we return a <strong>CANCEL_OR_REFUND<\/strong> webhook.<\/li>\n<li>For an unreferenced refund, we return a <strong>REFUND_WITH_DATA<\/strong> webhook.<\/li>\n<\/ul>\n<p>Depending on the card scheme and country\/region where the card is used, unreferenced refunds are sometimes processed synchronously. In that case the Terminal API response includes an <code>acquirerResponseCode<\/code> to indicate the outcome.<\/p>\n<p>To learn the <a href=\"\/pt\/point-of-sale\/basic-tapi-integration\/refund-payment\/refund-webhooks\">outcome of a refund<\/a>, you need to set up webhooks.<\/p>\n<h3 id=\"referenced-refund\">Handle a referenced refund<\/h3>\n<p>The Terminal API request for a referenced refund is a reversal request. The SDK contains a dedicated function for this.<\/p>\n<p>In your Android POS app, add code for the following steps:<\/p>\n<ol>\n<li>\n<p>Create a Terminal API reversal request with:<\/p>\n<ul>\n<li>\n<p><code>MessageHeader.POIID<\/code>: the installation ID of the SDK.<\/p>\n<ul>\n<li>If you create the Terminal API reversal request in your POS app, use <code>InPersonPayments.getInstallationId()<\/code> as the <code>POIID<\/code> in the <a href=\"\/pt\/point-of-sale\/design-your-integration\/terminal-api#request-message-header\">MessageHeader<\/a> of the request.<\/li>\n<li>If you create the Terminal API reversal request in the backend, this uses the  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/possdk\/latest\/post\/sessions#responses-201-installationId\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">installationId<\/a> from the <a href=\"#session\"><code>\/checkout\/possdk\/v68\/sessions<\/code> response<\/a>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>The remaining <code>MessageHeader<\/code> parameters and the request body.<\/p>\n<div class=\"sc-notice info\"><div>\n<p>For details, see <a href=\"\/pt\/point-of-sale\/basic-tapi-integration\/refund-payment\/referenced\">Referenced refund<\/a> and  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/terminal-api\/latest\/post\/reversal\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ReversalRequest<\/a>.<\/p>\n<\/div><\/div>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Create an instance of <code>TransactionRequest<\/code> using <code>TransactionReversalRequest.createReversal(nexoRequest: String)<\/code>, and pass the Terminal API payment request from your POS app or backend.<\/p>\n<\/li>\n<li>\n<p>Register a listener for the <code>PaymentResult<\/code> and pass the <code>transactionResponse<\/code> to your POS app. This is the Terminal API payment response, including data you can use to generate a receipt.<\/p>\n<pre><code class=\"language-kotlin\">val paymentLauncher = InPersonPayments.registerForPaymentResult(this) { refundResult -&gt;\n    \/\/ Handle refund response here.\n    \/\/...\n}<\/code><\/pre>\n<\/li>\n<li>\n<p>Invoke <code>performReversal()<\/code> with your transaction data and <code>authenticationProvider<\/code>.<br \/>\nNote that <code>authenticationProvider<\/code> is an implementation of the <a href=\"\/pt\/#enable-transactions\">AuthenticationProvider interface<\/a>, which extracts the <code>sdkData<\/code> from the server response.<\/p>\n<pre><code class=\"language-kotlin\">public suspend fun performReversal(\n    TransactionReversalRequest: TransactionReversalRequest,\n): Result&lt;PaymentResult&gt;<\/code><\/pre>\n<\/li>\n<li>\n<p>Check the <code>refundResult<\/code> that you receive in the <code>paymentLauncher<\/code> callback.<\/p>\n<\/li>\n<li>\n<p>Pass the <code>refundResult<\/code> to your POS app.<\/p>\n<\/li>\n<\/ol>\n<h3 id=\"unreferenced-refund\">Handle an unreferenced refund<\/h3>\n<p>The Terminal API request for an unreferenced refund is a payment request with an additional <code>paymentType<\/code> parameter:<\/p>\n<pre><code class=\"language-kotlin\">\/*\n * Assuming you've defined serializable [PaymentRequest] and [PaymentData] classes\n *\/\nval paymentRequest = PaymentRequest(\n    paymentData = PaymentData(\n        paymentType = PaymentType.Refund,\n    ),\n)<\/code><\/pre>\n<p>This means you can use the same code as for <a href=\"#payment\">handling a payment<\/a>. The only difference is the structure of the Terminal API payment request that you pass as the payload to the <code>TransactionRequest<\/code>.<\/p>\n<div class=\"sc-notice info\"><div>\n<p>For the structure of the Terminal API request, see <a href=\"\/pt\/point-of-sale\/basic-tapi-integration\/refund-payment\/unreferenced\">Unreferenced refund<\/a>.<\/p>\n<\/div><\/div>\n<h2 id=\"diagnosis\">10. Diagnose the device<\/h2>\n<p>We recommend implementing the Terminal API diagnosis request. This enables you to do the following:<\/p>\n<ul>\n<li>\n<p>Check for <strong>security threats<\/strong> that would block transactions. If threats are detected that an operator can solve, the response includes information about the cause and solution of the problem.<\/p>\n<\/li>\n<li>\n<p>Check the <strong>expiry date of the SDK<\/strong> that is used on the mobile device. <a href=\"\/pt\/point-of-sale\/mobile-android\/manage\/#keep-the-mobile-sdk-up-to-date\">Transactions will be blocked<\/a> if mandatory updates are not carried out.<\/p>\n<\/li>\n<\/ul>\n<p>In your Android POS app, add code for the following steps:<\/p>\n<ol>\n<li>\n<p>Create a Terminal API diagnosis request with:<\/p>\n<ul>\n<li>\n<p><code>MessageHeader.POIID<\/code>: the installation ID of the SDK.<\/p>\n<ul>\n<li>If you create the Terminal API diagnosis request in your POS app, use <code>InPersonPayments.getInstallationId()<\/code> as the <code>POIID<\/code> in the <a href=\"\/pt\/point-of-sale\/design-your-integration\/terminal-api#request-message-header\">MessageHeader<\/a> of the request.<\/li>\n<li>If you create the Terminal API diagnosis request in the backend, this uses the  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/possdk\/latest\/post\/sessions#responses-201-installationId\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">installationId<\/a> from the <a href=\"#session\"><code>\/checkout\/possdk\/v68\/sessions<\/code> response<\/a>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>The remaining <code>MessageHeader<\/code> parameters.<\/p>\n<\/li>\n<li>\n<p>The request body consisting of <code>DiagnosisRequest.HostDiagnosisFlag<\/code>: set to <strong>true<\/strong>, so that the SDK will try to  perform a security scan.<\/p>\n<\/li>\n<\/ul>\n<div class=\"sc-notice info\"><div>\n<p>For details, see <a href=\"\/pt\/point-of-sale\/diagnostics\/request-diagnosis#diagnosis-request-mobile\">Diagnose a Mobile SDK solution<\/a> and  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/terminal-api\/latest\/post\/diagnosis\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DiagnosisRequest<\/a>.<\/p>\n<\/div><\/div>\n<\/li>\n<li>\n<p>Create an instance of <code>DiagnosisRequest<\/code> using <code>DiagnosisRequest.create(nexoRequest)<\/code>, and pass the Terminal API diagnosis request from your POS app or backend.<\/p>\n<pre><code class=\"language-kotlin\">val diagnosisRequest = DiagnosisRequest.create(nexoRequest)<\/code><\/pre>\n<\/li>\n<li>\n<p>Invoke <code>InPersonPayments.performDiagnosis()<\/code> with your diagnosis data and diagnosis launcher.<\/p>\n<pre><code class=\"language-kotlin\">InPersonPayments.performDiagnosis(diagnosisRequest)<\/code><\/pre>\n<\/li>\n<li>\n<p>Check the response that you received:<\/p>\n<ul>\n<li>\n<p>Base64-decode the <code>attestationStatus<\/code> value for information about any security issues. If issues are detected that can be resolved by the end user, the resulting JSON object includes messages with the details. These are the same <a href=\"\/pt\/point-of-sale\/mobile-android\/troubleshooting#error-messages-for-the-android-sdk\">error messages<\/a> that we show automatically on the end user's mobile device when these issues are detected during a transaction.<\/p>\n<\/li>\n<li>\n<p>See the <code>sdkExpiry<\/code> for the date when the installed SDK version expires.<\/p>\n<\/li>\n<\/ul>\n<div class=\"sc-notice info\"><div>\n<p>For a detailed explanation of the response, see <a href=\"\/pt\/point-of-sale\/diagnostics\/request-diagnosis#diagnosis-request-mobile\">Diagnose a Mobile SDK solution<\/a>.<\/p>\n<\/div><\/div>\n<\/li>\n<\/ol>\n<h2>11. (Optional) Clear the session token<\/h2>\n<p>There are several situations when you need to clear the existing session to remove all session information from your mobile device. When you have cleared the session, configuration updates are fetched and a new session is established when you start a new transaction or call the warm-up function.<\/p>\n<p>As a best practice, clear the session to:<\/p>\n<ul>\n<li><strong>Re-establish a session after switching between merchant accounts or stores in your POS app and your Customer Area<\/strong>. If the device is reassigned from store A to store B and a transaction is started there, on the Adyen side the transaction will continue to appear to belong to store A instead of store B. Clearing the session prevents this issue.<\/li>\n<li><strong>Force a refresh of the configuration<\/strong>. After clearing the session, the latest configuration is fetched and stored on your mobile device the next time the Mobile SDK for Android connects to the Adyen backend.<\/li>\n<li><strong>Test the session establishment flow in your POS app<\/strong>, specifically how it interacts with your and Adyen's backend to securely establish a session with the Mobile SDK for Android.<\/li>\n<\/ul>\n<p>To clear the session:<\/p>\n<ol>\n<li>Explicitly clear the communication session using  <code>InPersonPayments.clearSession()<\/code> .<\/li>\n<li><a href=\"#session\">Establish a new communication session<\/a>.<\/li>\n<\/ol>\n<h2>11. (Optional) Optimize app size with Play Feature Delivery<\/h2>\n<p>It is possible to optimize the size of your Android Mobile SDK-enabled app with <a href=\"https:\/\/developer.android.com\/guide\/playcore\/feature-delivery\/on-demand\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Android's Play Feature Delivery<\/a>.<br \/>\nWith Play Feature Delivery, you can separate features from the base module of your app. This means that instead of a large, single download, users initially receive only your app's core functionalities (embedded features). Users can then later download and install the other (dynamic) features on demand. As a result, you will have a smaller initial app size, stay within <a href=\"https:\/\/support.google.com\/googleplay\/android-developer\/answer\/9859372?hl=en\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Google Play's size limits<\/a>, and provide a faster download experience.<\/p>\n<p>After you have followed the <a href=\"https:\/\/developer.android.com\/guide\/playcore\/feature-delivery\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Google Play instructions<\/a> to set up your app to use Play Feature Delivery, do the following:<\/p>\n<ul>\n<li>Add this dependency to your app module implementation: <code>com.adyen.ipp:dynamic-base:$version<\/code><\/li>\n<li>Add the other SDK dependencies to your feature module as you would normally do.<\/li>\n<\/ul>\n<div class=\"notices green\">\n<p><a href=\"https:\/\/github.com\/Adyen\/adyen-pos-mobile-android\/tree\/main\/app-dynamic\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Refer to this example implementation<\/a> of the Adyen POS Mobile SDK using an Android Dynamic Feature Module.<\/p>\n<\/div>\n<h2>Other supported features<\/h2>\n<p>In addition to <a href=\"#payment\">payments<\/a>, <a href=\"#referenced-refund\">refunds<\/a>, and <a href=\"#diagnosis\">diagnosis<\/a>, the Mobile solutions support other (payment) features. These are the same features that are supported in Terminal API integrations using Adyen-provided payment terminals.<\/p>\n<p>For some features you need to add parameters to your Terminal API payment request, similar to <a href=\"#unreferenced-refund\">unreferenced refunds<\/a> described above. Other features only require enabling the feature for your Adyen account. You can find the details on the pages dedicated to those features. Where the details differ between an integration using payment terminals and a mobile solution, this is clearly indicated.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">Feature<\/th>\n<th style=\"text-align: center;\">Supported with Card reader Android<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\">Diagnosis<\/td>\n<td style=\"text-align: center;\"><img title=\"-white_check_mark-\" alt=\"-white_check_mark-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/white_check_mark.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><a href=\"\/pt\/point-of-sale\/partial-payments\/\">Partial authorization<\/a><\/td>\n<td style=\"text-align: center;\"><img title=\"-white_check_mark-\" alt=\"-white_check_mark-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/white_check_mark.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Payment<\/td>\n<td style=\"text-align: center;\"><img title=\"-white_check_mark-\" alt=\"-white_check_mark-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/white_check_mark.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><a href=\"\/pt\/point-of-sale\/pre-authorisation\/\">Pre-authorization<\/a><\/td>\n<td style=\"text-align: center;\"><img title=\"-white_check_mark-\" alt=\"-white_check_mark-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/white_check_mark.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Refund, referenced<\/td>\n<td style=\"text-align: center;\"><img title=\"-white_check_mark-\" alt=\"-white_check_mark-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/white_check_mark.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Refund, unreferenced<\/td>\n<td style=\"text-align: center;\"><img title=\"-white_check_mark-\" alt=\"-white_check_mark-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/white_check_mark.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><a href=\"\/pt\/point-of-sale\/offline-payment\/\">Store and forward<\/a> offline payments<\/td>\n<td style=\"text-align: center;\"><img title=\"-x-\" alt=\"-x-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/x.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><a href=\"\/pt\/point-of-sale\/surcharge\/\">Surcharge<\/a><\/td>\n<td style=\"text-align: center;\"><img title=\"-x-\" alt=\"-x-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/x.png\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><a href=\"\/pt\/point-of-sale\/shopper-recognition\/tax-free-shopping\/\">Tax-free shopping<\/a><\/td>\n<td style=\"text-align: center;\"><img title=\"-x-\" alt=\"-x-\" class=\"smileys\" src=\"\/user\/data\/smileys\/emoji\/x.png\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Test your solution<\/h2>\n<p>To make test transactions:<\/p>\n<ol>\n<li>\n<p>Make sure you are using the test version of the Mobile SDK.  <\/p>\n<\/li>\n<li>\n<p>Initiate a test transaction using the following Adyen point-of-sale test cards to complete the payment:<\/p>\n<ul>\n<li><a href=\"\/pt\/point-of-sale\/testing-pos-payments\/test-card-v3\/\">White-green test card<\/a><\/li>\n<li><a href=\"\/pt\/point-of-sale\/testing-pos-payments\/test-card-v2\/\">Blue-green test card<\/a> version <strong>2.4<\/strong> or later<\/li>\n<\/ul>\n<p>The instructions are the same for both cards; see either of the pages mentioned above.<\/p>\n<\/li>\n<\/ol>\n<h2>Go live<\/h2>\n<p>When you have finished testing your integration and are ready to go live:<\/p>\n<ol>\n<li>\n<p>If new to Adyen, get a <a href=\"\/pt\/get-started-with-adyen\/#apply-for-your-live-account\">live account<\/a>. You need to have access to your organization's live Customer Area to generate API credentials for the live environment.<\/p>\n<\/li>\n<li>\n<p><a href=\"#get-the-live-sdk\">Get the live SDK<\/a>. You need to generate a new, live API key exclusively for downloading the SDK.<\/p>\n<\/li>\n<li>\n<p><a href=\"#establish-a-live-session\">Use the live endpoint for establishing a session<\/a>. To access the live endpoint, you need to generate a new, live API key that is different from the API key used for downloading the SDK.<\/p>\n<\/li>\n<li>\n<p>Optional. <a href=\"\/pt\/point-of-sale\/mobile-android\/manage#google-play\">Upload your app to Google Play<\/a>.<\/p>\n<\/li>\n<li>\n<p><a href=\"\/pt\/point-of-sale\/mobile-android\/manage#register-app\">Register your app with Adyen<\/a>.<\/p>\n<\/li>\n<\/ol>\n<h3>Get the live SDK<\/h3>\n<p>When going live, you need to get the release version of the SDK, which is available on the live repository. To access it, you need to change the repository URL as well as your API key.<\/p>\n<p>To pull in the live version of the SDK:<\/p>\n<ol>\n<li>\n<p>In your <a href=\"https:\/\/ca-live.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">live Customer Area<\/a>, generate a <a href=\"#add-sdk\">new API key<\/a> that only has the <strong>Allow SDK download for POS developers<\/strong> role.<\/p>\n<\/li>\n<li>\n<p>In your project's <code>build.gradle<\/code> file, change the <code>URL<\/code> to <code>https:\/\/pos-mobile.cdn.adyen.com\/adyen-pos-android<\/code> and replace <code>API_KEY<\/code> with your new API key.<\/p>\n<\/li>\n<li>\n<p>Add the <code>release<\/code> dependency to your <code>build.gradle<\/code> file.<\/p>\n<ul>\n<li>The live repository has both the <code>debug<\/code> and <code>release<\/code> artifacts. The <code>-debug<\/code> version can only access the test environment and the <code>-release<\/code> version can only access the live environment.<\/li>\n<li>When you have access to the live repository, you no longer need to use the test repository.<\/li>\n<li>In case of other custom build variants, use <code>&lt;buildVariantName&gt;Implementation 'com.adyen.ipp:pos-mobile-&lt;type&gt;:$version'<\/code> where <code>&lt;type&gt;<\/code> can be release (for production builds) or debug (for debug or development builds).<\/li>\n<\/ul>\n<pre><code class=\"language-groovy\">val version = 2.2.0\nreleaseImplementation 'com.adyen.ipp:pos-mobile-release:$version'\n\/\/ Be aware that importing additional modules will increase the size of your application.\n\/\/ To optimize your app's size and build times, only include the specific payment features you require.\nreleaseImplementation 'com.adyen.ipp:payment-tap-to-pay-release:$version'\nreleaseImplementation 'com.adyen.ipp:payment-card-reader-release:$version'<\/code><\/pre>\n<\/li>\n<\/ol>\n<h3>Establish a live session<\/h3>\n<p>When going live, you must change the <code>\/sessions<\/code> endpoint as well as the API key that you use to authenticate <code>\/sessions<\/code> requests.<\/p>\n<ul>\n<li>To access the live endpoint, generate a new API key from your <a href=\"https:\/\/ca-live.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">live Customer Area<\/a>.<\/li>\n<li>\n<p>The live endpoint URL contains a prefix which is unique to your company account, for example:<\/p>\n<p><code>https:\/\/{PREFIX}-checkout-live.adyenpayments.com\/checkout\/possdk\/v68\/sessions<\/code><\/p>\n<p>Get your <code>{PREFIX}<\/code> from your <a href=\"https:\/\/ca-live.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">live Customer Area<\/a> under <strong>Developers<\/strong> &gt; <strong>API URLs<\/strong> &gt; <strong>Prefix<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<h2>Next steps<\/h2>\n<div class=\"next-steps\" id=\"next-steps\" >\n<a href=\"\/point-of-sale\/mobile-android\/manage\" class=\"next-steps__step\" style=\"width:45%;\" target=\"_self\"><div class=\"next-steps__label\">required<\/div><p class=\"next-steps__body\"><div style=\"text-align: center;\"><img src=\"\/user\/themes\/adyen\/images\/illustrations\/settings.svg\"><h6 class=\"next-steps__title\">Manage your solution<\/h6><p>Make your solution available and keep the software up-to-date.<\/p><\/div><\/p><\/a><a href=\"\/point-of-sale\/mobile-android\/checklists\" class=\"next-steps__step\" style=\"width:45%;\" target=\"_self\"><p class=\"next-steps__body\"><div style=\"text-align: center;\"><img src=\"\/user\/themes\/adyen\/images\/illustrations\/checkmark.svg\"><h6 class=\"next-steps__title\">Checklists<\/h6><p>Get a list of what needs to be done to get started and go live with a Mobile solution.<\/p><\/div><\/p><\/a><a href=\"\/point-of-sale\/mobile-android\/troubleshooting\" class=\"next-steps__step\" style=\"width:45%;\" target=\"_self\"><p class=\"next-steps__body\"><div style=\"text-align: center;\"><img src=\"\/user\/themes\/adyen\/images\/illustrations\/close.svg\"><h6 class=\"next-steps__title\">Error handling<\/h6><p>Resolve errors that appear on the mobile Android device.<\/p><\/div><\/p><\/a><a href=\"\/point-of-sale\/user-manuals\/nyc1\" class=\"next-steps__step\" style=\"width:45%;\" target=\"_self\"><p class=\"next-steps__body\"><div style=\"text-align: center;\"><p><img style=\"width: 45px;\" alt=\"RFID card icon\" src=\"\/user\/pages\/reuse\/image-library\/01.icons\/rfid-card\/rfid-card.svg?decoding=auto&amp;fetchpriority=auto\"><\/p><h6 class=\"next-steps__title\">Use the card reader<\/h6><p>Learn how to connect and operate the NYC1 card reader.<\/p><\/div><\/p><\/a><a href=\"\/point-of-sale\/user-manuals\/nyc1-with-dock\" class=\"next-steps__step\" style=\"width:45%;\" target=\"_self\"><p class=\"next-steps__body\"><div style=\"text-align: center;\"><p><img style=\"width: 45px;\" alt=\"RFID card icon\" src=\"\/user\/pages\/reuse\/image-library\/01.icons\/rfid-card\/rfid-card.svg?decoding=auto&amp;fetchpriority=auto\"><\/p><h6 class=\"next-steps__title\">Use the card reader with a dock<\/h6><p>Learn how to connect and operate the NYC1 card reader and NYC1 dock.<\/p><\/div><\/p><\/a><\/div>\n","url":"https:\/\/docs.adyen.com\/pt\/point-of-sale\/mobile-android\/build\/card-reader","articleFields":{"description":"Integrate your POS app with the Adyen Mobile SDK for Android to make mobile payments using a card reader.","parameters":{"generic_sdk_name":"Mobile SDK","sdk_name":"Mobile SDK for Android","solution":"readerAndroid","solution_name":"Card reader on Android","platform":"Android"},"type":"page"},"algolia":{"url":"https:\/\/docs.adyen.com\/pt\/point-of-sale\/mobile-android\/build\/card-reader","title":"Card reader solution for Android","content":"With our Card reader on Android solution you can accept mobile in-person payments using a card reader as the payment interface, and process these payments on the plataforma de pagamentos da Adyen.\nThe card reader is connected with an Android mobile device through Bluetooth, or through USB using a dock. On the Android mobile device, payment requests are initiated from a POS app. On the card reader, the customer can tap, insert, or swipe their card, or use a digital wallet like Apple Pay.\nRequirements\nBefore you begin, take into account the following requirements, limitations, and preparations.\n\n\n\nRequirement\nDescription\n\n\n\n\nIntegration type\nYou must have a POS app that is integrated with Terminal API.\n\n\nAPI credentials\nYou need the following API credentials: To get the SDK, you must have an API credential with an API key and only the Allow SDK download for POS developers role. To establish a communication session, you must have an API credential with an API key, a client key, and the  Checkout webservice role.\n\n\nWebhooks\nTo learn the outcome of refunds, set up Standard webhooks (if this hasn't been done already).\n\n\nHardware\nYou need: An Android commercial off-the-shelf (COTS) mobile device. Must not be a payment terminal. An NYC1 card reader from Adyen and optionally an NYC1 dock. For PIN transactions your card reader needs to be an NYC1 model. See Android system requirements for the full hardware and software requirements.\n\n\nLimitations\nCheck the countries\/regions, payment methods, and functionality that we support for Card reader on Android.\n\n\nSetup steps\nBefore you begin: Ask our Support Team to enable your Adyen test account for using our Mobile solutions. In your Customer Area, order a test NYC1 card reader and a test card, and assign the reader to your store. If you want to disable PIN support for NYC1 card readers in the US from Mobile SDK for Android version 2.9.0 or later, contact our Support Team and ask them to disable PIN support on the company, merchant, or store level.\n\n\n\nHow it works\n\nSample app\nHit the ground running with our Android sample app.\n\nTo build a Tap to Pay on Android solution:\n\n\nAdd the Mobile SDK for Android to your project, either using an API key.\n\n\nImplement a server-to-server API request to establish a secure communication session.\n\n\nIn your POS app, enable the transaction functionality of the SDK.\n\n\nFrom your POS app, call the warmup function to speed up initiating transactions.\n\n\nIn your POS app, implement handling payments using the SDK.\nThis creates the following flow:\n\nYour Android POS app creates a Terminal API payment request, or receives a Terminal API payment request from your backend.\nThe POS app passes the payment request to the Android Mobile SDK.\nThe SDK initiates the transaction on the card reader.\nTo complete the payment, the customer taps the card reader with their payment card or phone (or other device) that has a digital wallet like Apple Pay.\nThe SDK passes the Terminal API payment response to the POS app.\n\n\n\nIn your POS app, implement handling refunds using the SDK.\n\n\nIf the same device will be used at multiple locations, implement clearing the communication session.\n\n\n1. Add the SDK to your project\nYou can add the Mobile SDK for Android to your POS app through a private Adyen repository. To get access, you need to have an Adyen API key that is used only for the purpose of getting the SDK.\n\nOur SDK only runs on Android 12 or later. You can still target earlier Android versions, but our SDK will not initialize.\n\nTo add the Mobile SDK to your project, you need to create an API credential with an API key that only has the Allow SDK download for POS developers role.\n\nThis API key is only meant to be used to get access to the SDK repository. To make a sessions request, you need a different API key.\n\nYou can share this API key with anybody in your team who needs to get the SDK, or you can create multiple API keys for internal use.\nTo add the SDK to your project:\n\n\nIn your Customer Area create an API credential with an API key:\n\n\nGo to Developers &gt; API credentials, and select Create new credential.\n\n\nUnder Payments &gt; Credential type select Web service user and then select Create credential.\n\n\nUnder Server settings &gt; Authentication select the API key tab and then select Generate API key.\n\n\nSelect the copy icon  and save your API key in a secure location.\n\n\nGo to Permissions &gt; Roles &gt; POS, select Allow SDK download for POS developers, and deselect any other permissions and roles.\n\nContact Support Team if you don't see the Allow SDK download for POS developers role.\n\n\n\nSelect Save changes.\n\n\n\n\nIn the repositories block of your project, usually defined in your settings.gradle file, add the URL to the remote repository where the SDK is stored, and add the API key that you created in the previous step.\ndependencyResolutionManagement {\n    \/\/...\n    repositories {\n        google()\n        mavenCentral()\n        maven {\n            url = uri(\"https:\/\/pos-mobile-test.cdn.adyen.com\/adyen-pos-android\")\n            credentials(HttpHeaderCredentials::class) {\n                name = \"x-api-key\"\n                value = \"&lt;YOUR_API_KEY&gt;\"\n            }\n            authentication {\n                create&lt;HttpHeaderAuthentication&gt;(\"header\")\n            }\n        }\n    }\n}\n\n\nIn your project's build.gradle file, add the package dependencies.\n\nTo find the latest val version check the release notes for the Mobile SDK for Android.\nFor the build type, note that -debug can only access the test environment, and -release can only access the live environment.\nIn case of other custom build variants, use &lt;buildVariantName&gt;Implementation 'com.adyen.ipp:pos-mobile-&lt;type&gt;:$version' where &lt;type&gt; can be release for production builds, or debug for debug or development builds.\n\nval version = 2.2.0\ndebugImplementation 'com.adyen.ipp:pos-mobile-debug:$version'\n\/\/ Be aware that importing additional modules will increase the size of your application.\n\/\/ To optimize your app's size and build times, only include the specific payment features you require.\ndebugImplementation 'com.adyen.ipp:payment-tap-to-pay-debug:$version'\ndebugImplementation 'com.adyen.ipp:payment-card-reader-debug:$version'\n\n\n2. Establish a session\nThe Mobile SDK has to communicate in a secure way with the plataforma de pagamentos da Adyen. For more information, see Communication session. \nTo authenticate your server-to-server API request for establishing a communication session, you need to have an Adyen API credential in your test Customer Area. This credential must have a client key and an API key with the following role:\n\nCheckout webservice role. This role is assigned by default when the API key is created.\nTo add a client key to an existing API credential, create a client key as follows:\n\nLog in to your Customer Area.\nGo to Developers &gt; API credentials, and select the credential username for your integration, for example ws@Company.[YourCompanyAccount].\nUnder Client settings &gt; Authentication select the Client key tab.\nSelect Generate client key.\n\nSelect Save changes.\n\nThe client key is part of the setup but is not used later on. Therefore, you do not need to specify allowed origins, and you do not need to save the client key in your system.\n\n\n\nTo let your backend establish a session, use the regular endpoint, or the dedicated endpoint for payment facilitators.\n\nRegular endpoint:  \/checkout\/possdk\/v68\/sessions\nPayment facilitator endpoint: \/softposconfig\/v3\/auth\/certificate\n\n\n\n    \n        \n        \n    \n\n\n3. Enable transactions\nTo enable the payments functionality of the Mobile SDK for Android, add code to your Android POS app:\n\n\nImplement the AuthenticationProvider interface. Note that you need to extract the  sdkData from the server response and create an AuthenticationResponse object with sdkData in the constructor. Below is an example of how you could do that, assuming your project uses OkHttp.\nclass MyAuthenticationProvider : AuthenticationProvider() {\n\n    override suspend fun authenticate(setupToken: String): Result&lt;AuthenticationResponse&gt; {\n\n        \/\/ Make a call to your backend to trigger a `\/checkout\/possdk\/v68\/sessions` request, specifying the `setupToken` provided by the SDK\n\n        val client = OkHttpClient()\n        val request = Request.Builder()\n            .url(\"ADDRESS_OF_YOUR_BACKEND_API\")\n            .build()\n\n        client.newCall(request).execute().use { response -&gt;\n            response.body?.let {\n                \/\/ parse your own back-end response and return AuthenticationResponse\n                \/\/...\n                return Result.success(AuthenticationResponse(sdkData))\n            }\n        }\n    }\n}\n\n\nImplement the MerchantAuthenticationService abstract class: in your implementation, provide an instance of your AuthenticationProvider from the previous step. If you use Dagger2\/Hilt dependency injection, below is an example of how you could do this:\nclass MyAuthenticationService : MerchantAuthenticationService() {\n\n    @Inject\n    override lateinit var authenticationProvider: AuthenticationProvider\n}\n\n\nAdd the service to your POS app's AndroidManifest.xml file.\n &lt;service android:name=\".MyAuthenticationService\" \/&gt;\n\n\nMake sure that the MerchantAuthenticationService can provide new sdkData at any time.\nIf there is no session or the session has expired, the service is called using the MerchantAuthenticationService.authenticate(setupToken) callback. Using the provided setupToken you need to get the sdkData through your backend and return it. For instructions, see Establish a session.\n\nThe Adyen POS Mobile SDK detects the MerchantAuthenticationService automatically. If the SDK fails to detect the service, an error will occur when SDK methods are called. To resolve this, you can manually set the service using InPersonPayments.setAuthenticationServiceClass().\n\n\n\nManage automatic initialization\nThe  initializes automatically, using the Android App Startup library. If you prefer to manually initialize the , add the following code to the POS app's AndroidManifest.xml file to disable the .\n &lt;provider\n     android:name=\"androidx.startup.InitializationProvider\"\n     android:authorities=\"${applicationId}.androidx-startup\"\n     android:exported=\"false\"\n     tools:node=\"merge\"&gt;\n     &lt;meta-data android:name=\"com.adyen.ipp.api.InPersonPaymentsInitializer\"\n               tools:node=\"remove\" \/&gt;\n &lt;\/provider&gt;\nTo manually initialize that component at a later point, add the following code to the POS app.\nFor  version 2.6.0 or later:\nSince the SDK requires the application to be in the foreground to bind to the service, you need to trigger initialization when your main Activity is visible. Use repeatOnLifecycle to ensure that the initialization runs when the Activity is in the RESUMED state. \noverride fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n\n    lifecycleScope.launch {\n        \/\/ Suspend execution until the Activity is RESUMED\n        repeatOnLifecycle(Lifecycle.State.RESUMED) {\n            val state = InPersonPaymentsTools.initializeManually(this@MainActivity)\n\n            if (state is InitializationState.SuccessfulInitialization) {\n                \/\/ SDK is ready\n            } else {\n                \/\/ Handle failure\n            }\n        }\n    }\n}\nFor  versions earlier than version 2.6.0:\nAppInitializer.getInstance(this)\n    .initializeComponent(InPersonPaymentsInitializer::class.java)\nInitialization status check\nTo check the status of the SDK initialization, you can use one of the following options.\nFor  version 2.6.0 or later:\nwhen (val state = InPersonPaymentsTools.getInitializationState()){\n    InitializationState.SuccessfulInitialization -&gt; {\n        \/\/ SDK is ready. You can now safely proceed.\n    }\n\n    is InitializationState.FailedInitialization -&gt; {\n        \/\/ Handle initialization failure. Log errors or notify the user.\n        Log.e(\"MyApp\", \"SDK initialization failed: ${state.failureReasons}\")\n    }\n\n    else -&gt; Unit\n}\nor for  versions earlier than version 2.6.0 if you need more precise control over the state flow:\nInPersonPayments.initialized\n    .filter { it == InitializationState.SuccessfulInitialization } \/\/ Wait until it is true.\n    .take(1)       \/\/ Take only one item.\n    .collect { ready -&gt;\n        if (ready) {\n            val id = InPersonPayments.getInstallationId()\n            \/\/...\n        }\n    }\nManage POS app dependency initialization\nThe code that you add to the Application.onCreate() method is executed for all processes. In some cases, it can be beneficial to skip the re-execution of the code, for example the initialization of your dependency graph or analytics libraries.\nThe following method evaluates specific conditions and returns a boolean value that indicates whether the initialization should be skipped.\nif (InPersonPaymentsTools.shouldSkipAppInitialize(context)) {\n    \/\/ Perform actions when initialization should be skipped\n} else {\n    \/\/ Proceed with application initialization\n}\nAdditionally, you can use the following functions:\n\n\nsuspend InPersonPaymentsTools.getInitializationState(): this function observes the initialization state of the SDK and pauses the calling coroutine until the SDK initialization finishes and reaches a success or failure state. You can use this suspend function if an action in your app depends on the SDK being fully initialized.\n\n\nsuspend InPersonPaymentsTools.initializeManually(): this function triggers initialization of the SDK and waits for the initialization to finish.\n\n\n4. Use the warm-up function\nTo speed up initiating transactions, you can use the warm-up function. This function checks for a session, configuration changes, and security checks if needed.\nAs a best practice, call the warm-up function after the SDK has initialized:\n\nWhen the POS app starts.\nWhen the POS app returns to the foreground.\n\nTo call the warm-up function:\nInPersonPayments.warmUp()\n5. (Optional) Avoid delays\nYou can avoid delays and speed up the transaction by preparing the card reader outside a transaction flow with configuration and security checks.\nWhen you start a transaction, the Mobile SDK connects with the card reader to check the reader's configuration. If the configuration is not up to date, the Mobile SDK sends the latest configuration files to the reader. This can take up to to 30 seconds. Additionally, the Mobile SDK performs a security check every 24 hours. To avoid a delay during the transaction flow, you can prepare the card reader by running these checks outside the transaction flow.\nIt is possible to start a transaction while the card reader preparation is running. There can be a short delay during the transaction while any remaining checks and configuration updates are completed.\nWe recommend preparing the device for transaction every 24 hours or when the configuration has changed.\nTo prepare the device outside a transaction flow, call the DeviceManager prepareDeviceForTransaction function  as follows, where the device is the card reader to prepare.\n\/\/ Get the DeviceManager\n        val deviceManager = AdyenCardReaders.getInstance(context).deviceManager\n        \/\/ Listen for when a device is connected\n        deviceManager.connectionState.collect { connectionState -&gt;\n            if(connectionState is CardReaderState.Connected) {\n                val device = connectionState.cardReaderInfo\n                \/\/ Prepare the connected device\n                deviceManager.prepareDeviceForTransaction(device)\n            }\n        }\n6. Manage the Device Manager UI\nTo use the card reader, operators need to:\n\nConnect the mobile device with the card reader through Bluetooth pairing or through USB using a dock or direct USB (if the Android device supports USB host mode).\nView an overview of card readers. For example, to switch to a different card reader.\nView details of the card reader they are using. For example, to check the battery charge level.\nUpdate the firmware of the card reader or the dock they are using.\n\nTo handle these tasks, the SDK provides Device Manager functions that enable you to either:\n\nUse the built-in UI.\nBuild a custom UI.\n\n\n\n    \n        \n        \n    \n\n\n7. Decide on transaction UI options\nIn this step you decide on the options that are available for customizing the transaction user interface.\nIf you want the UI to appear in dark mode, you need to enable this options in the settings of your mobile device.\nWhen you start a transaction, you can customize the user interface using merchantUiParameters and the optional fields for the following UI options:\n\n    \n    \n        \n            \n            \n                                    Add a logo\n                            \n        \n        \n            \nTo show a logo on your mobile device during the transaction flow use:\n\n\nmerchantLogo: Format can be SVG (recommended), WEBP, JPEG, or PNG. The logo is shown at 100dp&nbsp;x&nbsp;32dp (width&nbsp;x&nbsp;height) on top of the payment screen. Trim any transparent pixels from the logo asset, to show your logo as large as possible within the available space.\n(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  merchantLogo = R.drawable.merchant_logo,\n  \/\/ ...\n)\n\n\n\n        \n    \n\n\n\n    \n    \n        \n            \n            \n                                    Configure success screen duration\n                            \n        \n        \n            \nTo specify how long the success screen shows after a successful transaction use: \n\n\nautoDismissDelay: If not specified, this success screen is dismissed after 4 seconds. You can set a time in milliseconds with a minimum of 0.5&nbsp;seconds (500L) and a maximum of 4&nbsp;seconds (4000L).\n(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  autoDismissDelay = 3.seconds,\n  \/\/ ...\n)\n\n\n\n        \n    \n\n\n\n    \n    \n        \n            \n            \n                                    Customize position of the NFC tap indicator\n                            \n        \n        \n            \nBy default, the NFC tap indicator is an animation that points at the back of the device. You can customize the position of the NFC tap indicator on your mobile device screen to point at the location of your card reader. Then useCardReaderAnimationType. This allows you to show a chevron-type arrow (Simplified), pointing in the specified direction. If there is not enough room on the mobile device screen, no chevron-type arrow can be shown. Instead, a tap indicator is shown in the center of the screen. \n\n\nOptions for 'Simplified' are: CenterRight, or CenterLeft. \n\n\n\nCenterLeft\nCenterRight\n\n\n\n\n\n\n\n\n\n(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  cardReaderUiParameters = CardReaderUiParameters.create(\n      animation = CardReaderAnimationType.simplified(Position.Center),\n  ),\n  \/\/ ...\n)\n\n\n\n        \n    \n\n\n8. Handle a payment\nIn this step you add code to start a transaction with:\n\nA Terminal API payment request.\n\nThe card reader as the payment interface to use. \n\nTo let the Mobile SDK handle transactions:\n\n\nIn your POS app, create a Terminal API payment request with:\n\n\nMessageHeader.POIID: the installation ID of the SDK.\n\nIf you create the Terminal API payment request in your POS app, use InPersonPayments.getInstallationId() as the POIID in the MessageHeader of the request.\nIf you create the Terminal API payment request in the backend, this uses the  installationId from the \/checkout\/possdk\/v68\/sessions response.\n\n\n\nThe remaining MessageHeader parameters and the request body.\n\nFor details, see Make a payment and PaymentRequest.\n\n\n\n\n\nCreate an instance of TransactionRequest using TransactionRequest.create(nexoRequest), and pass the Terminal API payment request from your POS app or backend.\nval transactionRequest = TransactionRequest.create(nexoRequest)\n\n\nGet a PaymentInterface from InPersonPayments using  InPersonPayments.getPaymentInterface(CardReader). \nval paymentInterface = InPersonPayments.getPaymentInterface(CardReader)\n\n\nRegister a listener for the PaymentResult and pass the transactionResponse to your POS app. This is the Terminal API payment response, including data you can use to generate a receipt.\nInPersonPayments.registerForPaymentResult(context) { result -&gt;\n  result.fold(\n    onSuccess = { paymentResult: PaymentResult -&gt;\n        \/*\n         * Here is your success case logic, for example:\n         * if (paymentResult.success) \"Payment Successful\" else \"Payment Unsuccessful\"\n         *\/\n    },\n    onFailure = { error: Throwable -&gt;\n        \/*\n         * Here is your failure case logic, for example:\n         * Log.e(\"InPersonPaymentsResult\", \"Payment Failed\", error)\n         *\/\n    },\n)\n\n\nInvoke InPersonPayments.performTransaction() with your transaction data, payment launcher, and authentication service. \nThen customize the user interface using merchantUiParameters with the optional fields that you decided on in the previous step. The following example invokes InPersonPayments.performTransaction() and includes parameters to add a custom logo and customizing the position of the NFC tap indicator on your mobile device screen:\nInPersonPayments.performTransaction(\n    context = this@DevAmountEntryActivity,\n    paymentLauncher = paymentLauncher,\n    paymentInterface = result.paymentInterface,\n    transactionRequest = result.transactionRequest,\n    merchantUiParameters = MerchantUiParameters.create(\n        merchantLogo = R.drawable.merchant_logo,\n        tapToPayUiParameters = TapToPayUiParameters.create(\n            animation = TapToPayAnimationType.front(NfcFrontPosition.TopCenter),\n        ),\n        cardReaderUiParameters = CardReaderUiParameters(\n            animation = CardReaderAnimationType.simplified(Position.CenterLeft),\n        ),\n    ),\n)\nThe Mobile SDK checks for a session, starts the transaction, and shows screens on your mobile device to help the customer.\n\n\n\nIf the shopper does not present their payment method within 30 seconds, the payment request times out. If that happens, you need to make another payment request.\n\n9. Handle a refund\nThere are two types of refund: referenced and unreferenced. The main difference is that a referenced refund is connected to the original payment, and an unreferenced refund isn't. That makes unreferenced refunds a bit riskier. For an overview of the differences, see Refund a payment.\nRefunds are usually not processed synchronously. When you send a request for a referenced or unreferenced refund, the Terminal API response only confirms we received the request. \nWe inform you about the outcome of the refund asynchronously, through a webhook.\n\nFor a referenced refund, we return a CANCEL_OR_REFUND webhook.\nFor an unreferenced refund, we return a REFUND_WITH_DATA webhook.\n\nDepending on the card scheme and country\/region where the card is used, unreferenced refunds are sometimes processed synchronously. In that case the Terminal API response includes an acquirerResponseCode to indicate the outcome.\nTo learn the outcome of a refund, you need to set up webhooks.\nHandle a referenced refund\nThe Terminal API request for a referenced refund is a reversal request. The SDK contains a dedicated function for this.\nIn your Android POS app, add code for the following steps:\n\n\nCreate a Terminal API reversal request with:\n\n\nMessageHeader.POIID: the installation ID of the SDK.\n\nIf you create the Terminal API reversal request in your POS app, use InPersonPayments.getInstallationId() as the POIID in the MessageHeader of the request.\nIf you create the Terminal API reversal request in the backend, this uses the  installationId from the \/checkout\/possdk\/v68\/sessions response.\n\n\n\nThe remaining MessageHeader parameters and the request body.\n\nFor details, see Referenced refund and  ReversalRequest.\n\n\n\n\n\nCreate an instance of TransactionRequest using TransactionReversalRequest.createReversal(nexoRequest: String), and pass the Terminal API payment request from your POS app or backend.\n\n\nRegister a listener for the PaymentResult and pass the transactionResponse to your POS app. This is the Terminal API payment response, including data you can use to generate a receipt.\nval paymentLauncher = InPersonPayments.registerForPaymentResult(this) { refundResult -&gt;\n    \/\/ Handle refund response here.\n    \/\/...\n}\n\n\nInvoke performReversal() with your transaction data and authenticationProvider.\nNote that authenticationProvider is an implementation of the AuthenticationProvider interface, which extracts the sdkData from the server response.\npublic suspend fun performReversal(\n    TransactionReversalRequest: TransactionReversalRequest,\n): Result&lt;PaymentResult&gt;\n\n\nCheck the refundResult that you receive in the paymentLauncher callback.\n\n\nPass the refundResult to your POS app.\n\n\nHandle an unreferenced refund\nThe Terminal API request for an unreferenced refund is a payment request with an additional paymentType parameter:\n\/*\n * Assuming you've defined serializable [PaymentRequest] and [PaymentData] classes\n *\/\nval paymentRequest = PaymentRequest(\n    paymentData = PaymentData(\n        paymentType = PaymentType.Refund,\n    ),\n)\nThis means you can use the same code as for handling a payment. The only difference is the structure of the Terminal API payment request that you pass as the payload to the TransactionRequest.\n\nFor the structure of the Terminal API request, see Unreferenced refund.\n\n10. Diagnose the device\nWe recommend implementing the Terminal API diagnosis request. This enables you to do the following:\n\n\nCheck for security threats that would block transactions. If threats are detected that an operator can solve, the response includes information about the cause and solution of the problem.\n\n\nCheck the expiry date of the SDK that is used on the mobile device. Transactions will be blocked if mandatory updates are not carried out.\n\n\nIn your Android POS app, add code for the following steps:\n\n\nCreate a Terminal API diagnosis request with:\n\n\nMessageHeader.POIID: the installation ID of the SDK.\n\nIf you create the Terminal API diagnosis request in your POS app, use InPersonPayments.getInstallationId() as the POIID in the MessageHeader of the request.\nIf you create the Terminal API diagnosis request in the backend, this uses the  installationId from the \/checkout\/possdk\/v68\/sessions response.\n\n\n\nThe remaining MessageHeader parameters.\n\n\nThe request body consisting of DiagnosisRequest.HostDiagnosisFlag: set to true, so that the SDK will try to  perform a security scan.\n\n\n\nFor details, see Diagnose a Mobile SDK solution and  DiagnosisRequest.\n\n\n\nCreate an instance of DiagnosisRequest using DiagnosisRequest.create(nexoRequest), and pass the Terminal API diagnosis request from your POS app or backend.\nval diagnosisRequest = DiagnosisRequest.create(nexoRequest)\n\n\nInvoke InPersonPayments.performDiagnosis() with your diagnosis data and diagnosis launcher.\nInPersonPayments.performDiagnosis(diagnosisRequest)\n\n\nCheck the response that you received:\n\n\nBase64-decode the attestationStatus value for information about any security issues. If issues are detected that can be resolved by the end user, the resulting JSON object includes messages with the details. These are the same error messages that we show automatically on the end user's mobile device when these issues are detected during a transaction.\n\n\nSee the sdkExpiry for the date when the installed SDK version expires.\n\n\n\nFor a detailed explanation of the response, see Diagnose a Mobile SDK solution.\n\n\n\n11. (Optional) Clear the session token\nThere are several situations when you need to clear the existing session to remove all session information from your mobile device. When you have cleared the session, configuration updates are fetched and a new session is established when you start a new transaction or call the warm-up function.\nAs a best practice, clear the session to:\n\nRe-establish a session after switching between merchant accounts or stores in your POS app and your Customer Area. If the device is reassigned from store A to store B and a transaction is started there, on the Adyen side the transaction will continue to appear to belong to store A instead of store B. Clearing the session prevents this issue.\nForce a refresh of the configuration. After clearing the session, the latest configuration is fetched and stored on your mobile device the next time the Mobile SDK for Android connects to the Adyen backend.\nTest the session establishment flow in your POS app, specifically how it interacts with your and Adyen's backend to securely establish a session with the Mobile SDK for Android.\n\nTo clear the session:\n\nExplicitly clear the communication session using  InPersonPayments.clearSession() .\nEstablish a new communication session.\n\n11. (Optional) Optimize app size with Play Feature Delivery\nIt is possible to optimize the size of your Android Mobile SDK-enabled app with Android's Play Feature Delivery.\nWith Play Feature Delivery, you can separate features from the base module of your app. This means that instead of a large, single download, users initially receive only your app's core functionalities (embedded features). Users can then later download and install the other (dynamic) features on demand. As a result, you will have a smaller initial app size, stay within Google Play's size limits, and provide a faster download experience.\nAfter you have followed the Google Play instructions to set up your app to use Play Feature Delivery, do the following:\n\nAdd this dependency to your app module implementation: com.adyen.ipp:dynamic-base:$version\nAdd the other SDK dependencies to your feature module as you would normally do.\n\n\nRefer to this example implementation of the Adyen POS Mobile SDK using an Android Dynamic Feature Module.\n\nOther supported features\nIn addition to payments, refunds, and diagnosis, the Mobile solutions support other (payment) features. These are the same features that are supported in Terminal API integrations using Adyen-provided payment terminals.\nFor some features you need to add parameters to your Terminal API payment request, similar to unreferenced refunds described above. Other features only require enabling the feature for your Adyen account. You can find the details on the pages dedicated to those features. Where the details differ between an integration using payment terminals and a mobile solution, this is clearly indicated.\n\n\n\nFeature\nSupported with Card reader Android\n\n\n\n\nDiagnosis\n\n\n\nPartial authorization\n\n\n\nPayment\n\n\n\nPre-authorization\n\n\n\nRefund, referenced\n\n\n\nRefund, unreferenced\n\n\n\nStore and forward offline payments\n\n\n\nSurcharge\n\n\n\nTax-free shopping\n\n\n\n\nTest your solution\nTo make test transactions:\n\n\nMake sure you are using the test version of the Mobile SDK.  \n\n\nInitiate a test transaction using the following Adyen point-of-sale test cards to complete the payment:\n\nWhite-green test card\nBlue-green test card version 2.4 or later\n\nThe instructions are the same for both cards; see either of the pages mentioned above.\n\n\nGo live\nWhen you have finished testing your integration and are ready to go live:\n\n\nIf new to Adyen, get a live account. You need to have access to your organization's live Customer Area to generate API credentials for the live environment.\n\n\nGet the live SDK. You need to generate a new, live API key exclusively for downloading the SDK.\n\n\nUse the live endpoint for establishing a session. To access the live endpoint, you need to generate a new, live API key that is different from the API key used for downloading the SDK.\n\n\nOptional. Upload your app to Google Play.\n\n\nRegister your app with Adyen.\n\n\nGet the live SDK\nWhen going live, you need to get the release version of the SDK, which is available on the live repository. To access it, you need to change the repository URL as well as your API key.\nTo pull in the live version of the SDK:\n\n\nIn your live Customer Area, generate a new API key that only has the Allow SDK download for POS developers role.\n\n\nIn your project's build.gradle file, change the URL to https:\/\/pos-mobile.cdn.adyen.com\/adyen-pos-android and replace API_KEY with your new API key.\n\n\nAdd the release dependency to your build.gradle file.\n\nThe live repository has both the debug and release artifacts. The -debug version can only access the test environment and the -release version can only access the live environment.\nWhen you have access to the live repository, you no longer need to use the test repository.\nIn case of other custom build variants, use &lt;buildVariantName&gt;Implementation 'com.adyen.ipp:pos-mobile-&lt;type&gt;:$version' where &lt;type&gt; can be release (for production builds) or debug (for debug or development builds).\n\nval version = 2.2.0\nreleaseImplementation 'com.adyen.ipp:pos-mobile-release:$version'\n\/\/ Be aware that importing additional modules will increase the size of your application.\n\/\/ To optimize your app's size and build times, only include the specific payment features you require.\nreleaseImplementation 'com.adyen.ipp:payment-tap-to-pay-release:$version'\nreleaseImplementation 'com.adyen.ipp:payment-card-reader-release:$version'\n\n\nEstablish a live session\nWhen going live, you must change the \/sessions endpoint as well as the API key that you use to authenticate \/sessions requests.\n\nTo access the live endpoint, generate a new API key from your live Customer Area.\n\nThe live endpoint URL contains a prefix which is unique to your company account, for example:\nhttps:\/\/{PREFIX}-checkout-live.adyenpayments.com\/checkout\/possdk\/v68\/sessions\nGet your {PREFIX} from your live Customer Area under Developers &gt; API URLs &gt; Prefix.\n\n\nNext steps\n\nrequiredManage your solutionMake your solution available and keep the software up-to-date.ChecklistsGet a list of what needs to be done to get started and go live with a Mobile solution.Error handlingResolve errors that appear on the mobile Android device.Use the card readerLearn how to connect and operate the NYC1 card reader.Use the card reader with a dockLearn how to connect and operate the NYC1 card reader and NYC1 dock.\n","type":"page","locale":"pt","boost":16,"hierarchy":{"lvl0":"Home","lvl1":"Terminais","lvl2":"Android Mobile solutions","lvl3":"Build your Android Mobile solution","lvl4":"Card reader solution for Android"},"hierarchy_url":{"lvl0":"https:\/\/docs.adyen.com\/pt","lvl1":"https:\/\/docs.adyen.com\/pt\/point-of-sale","lvl2":"https:\/\/docs.adyen.com\/pt\/point-of-sale\/mobile-android","lvl3":"https:\/\/docs.adyen.com\/pt\/point-of-sale\/mobile-android\/build","lvl4":"\/pt\/point-of-sale\/mobile-android\/build\/card-reader"},"levels":5,"category":"In-person payments","category_color":"green","tags":["reader","solution","Android"]},"articleFiles":{"front-bottomcenter.svg":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/03.point-of-sale\/55.mobile-android\/06.build\/02.card-reader\/front-bottomcenter.svg\" \/>"}}
