{"title":"Tap to Pay on Android","category":"default","creationDate":1683747600,"content":"<p>With our Tap to Pay on Android solution you can accept contactless in-person payments using an Android mobile device as the payment interface, and process these payments on the plataforma de pagamentos da Adyen.<\/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;\">An Android commercial off-the-shelf (COTS) mobile device with an integrated NFC reader. Must not be a payment terminal. 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 Tap to Pay 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>  enable your Adyen test account for using our Mobile solutions.<\/li><li markdown=\"1\"><a href=\"\/pt\/point-of-sale\/managing-terminals\/order-terminals#sales-order-steps\">Order<\/a> a test card.<\/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, 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. The SDK initializes automatically, but you can change that.<\/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 Mobile SDK.<\/li>\n<li>The SDK initiates the transaction on the card reader.<br \/>\nTo complete the payment, the customer taps the NFC reader on your mobile device 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=\"tabuJs0Z\">\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 Mobile SDK <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 Mobile SDK, add the following code to the POS app's <code>AndroidManifest.xml<\/code> file to disable the Mobile SDK.<\/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 Mobile SDK 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 Mobile SDK 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 Mobile SDK 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 Mobile SDK 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 id=\"transaction-ui-options\">5. 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  \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>The default UI is designed for devices with the NFC antenna at the top rear. It shows an animation that points at the antenna's location on the back of the device. If the NFC antenna on your device is located in a different position, you can customize the position of the tap indicator on the mobile device screen. You need to identify the position of the device's NFC antenna and use <code>tapToPayUiParameters<\/code>. Options can be <code>Directional<\/code> to show a chevron-type arrow, pointing in the specified direction, or <code>Front<\/code> to a static image of an NFC logo.<\/p>\n<ul>\n<li>Options for <code>Directional<\/code> are: <code>TopCenter<\/code>, or <code>BottomCenter<\/code>.<\/li>\n<\/ul>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">TopCenter<\/th>\n<th style=\"text-align: center;\">BottomCenter<\/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\/kiosk_TopCenter.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\/kiosk_BottomCenter.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"language-kotlin\">  (...)\n  merchantUiParameters = MerchantUiParameters.create(\n      tapToPayUiParameters = TapToPayUiParameters.create(\n          animation = TapToPayAnimationType.directional(NfcDirectionalPosition.BottomCenter),\n      ),\n      \/\/ ...\n  )<\/code><\/pre>\n<ul>\n<li>\n<p>Options for <code>Front<\/code> are: <code>TopCenter<\/code>, <code>Center<\/code>, or <code>BottomCenter<\/code>.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">TopCenter<\/th>\n<th style=\"text-align: center;\">Center<\/th>\n<th style=\"text-align: center;\">BottomCenter<\/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\/kiosk_NFCTopCenter.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\/kiosk_NFCCenter.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\/kiosk_NFCBottomCenter.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"language-kotlin\">(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  tapToPayUiParameters = TapToPayUiParameters.create(\n      animation = TapToPayAnimationType.front(NfcFrontPosition.BottomCenter),\n  ),\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-nfc-tap-indicator-in-kiosk-mode\">\n                                    <h4 class=\"adl-accordion__title\">Customize position of NFC tap indicator in kiosk mode<\/h4>\n                            <\/div>\n        <\/div>\n        <div role=\"region\" class=\"adl-accordion__content\">\n            \n<p>When in kiosk mode, the default position of the tap indicator is at the bottom-center of the device screen. You need to identify the position of your mobile device's NFC antenna to customize the position of the NFC tap indicator on your mobile device screen in <a href=\"\/pt\/point-of-sale\/mobile-android\/understand#kiosk-mode\">kiosk mode<\/a>. Then use <code>TapToPayKioskAnimationType<\/code> for placement options for the NFC tap indicator. The indicator can either be a static image of an NFC logo (<code>Front<\/code>) or an animated chevron-type arrow (<code>Directional<\/code>).<\/p>\n<ul>\n<li>\n<p>Options for <code>Front<\/code> are: <code>TopCenter<\/code>, <code>Center<\/code>, <code>BottomCenter<\/code>, <code>LeftCenter<\/code>, or <code>RightCenter<\/code>. <\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">TopCenter<\/th>\n<th style=\"text-align: center;\">Center<\/th>\n<th style=\"text-align: center;\">BottomCenter<\/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\/kiosk_NFCTopCenter.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\/kiosk_NFCCenter.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\/kiosk_NFCBottomCenter.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">LeftCenter<\/th>\n<th style=\"text-align: center;\">RightCenter<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: center;\"><img style=\"width: 230px;\" alt=\"\" src=\"\/user\/pages\/reuse\/pos-mobile-sdk\/android-build\/transaction-ui-options\/kiosk_NFCLeftCenter.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<td style=\"text-align: center;\"><img style=\"width: 230px;\" alt=\"\" src=\"\/user\/pages\/reuse\/pos-mobile-sdk\/android-build\/transaction-ui-options\/kiosk_NFCRightCenter.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"language-kotlin\">(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  kioskModeUiParameters = KioskModeUiParameters.create(\n     tapToPayKioskAnimation = TapToPayKioskAnimationType.front(NfcFrontPosition.TopCenter),\n  ),\n  \/\/ ...\n)<\/code><\/pre>\n<\/li>\n<li>\n<p>Options for <code>Directional<\/code> are: <code>TopLeftFacingLeft<\/code>, <code>TopLeft<\/code>, <code>TopCenter<\/code>, <code>TopRight<\/code>, <code>TopRightFacingRight<\/code>, <code>CenterLeft<\/code>, <code>CenterRight<\/code>, <code>BottomLeftFacingLeft<\/code>, <code>BottomLeft<\/code>, <code>BottomCenter<\/code> (default value), <code>BottomRight<\/code>, or <code>BottomRightFacingRight<\/code>.      <\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">TopLeft<\/th>\n<th style=\"text-align: center;\">TopCenter<\/th>\n<th style=\"text-align: center;\">TopRight<\/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\/kiosk_TopLeft.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\/kiosk_TopCenter.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\/kiosk_TopRight.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">BottomLeft<\/th>\n<th style=\"text-align: center;\">BottomCenter<\/th>\n<th style=\"text-align: center;\">BottomRight<\/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\/kiosk_BottomLeft.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\/kiosk_BottomCenter.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\/kiosk_BottomRight.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">BottomLeftFacingLeft<\/th>\n<th style=\"text-align: center;\">TopRightFacingRight<\/th>\n<th style=\"text-align: center;\">BottomRightFacingRight<\/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\/kiosk_BottomLeftFacingLeft.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\/kiosk_TopRightFacingRight.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\/kiosk_BottomRightFacingRight.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">TopLeftFacingLeft<\/th>\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\/kiosk_TopLeftFacingLeft.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\/kiosk_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\/kiosk_CenterRight.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"language-kotlin\">(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  kioskModeUiParameters = KioskModeUiParameters.create(\n      tapToPayKioskAnimation = TapToPayKioskAnimationType.directional(NfcDirectionalPosition.CenterLeft),\n  ),\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-pin-input-area-in-kiosk-mode\">\n                                    <h4 class=\"adl-accordion__title\">Customize position of PIN input area in kiosk mode<\/h4>\n                            <\/div>\n        <\/div>\n        <div role=\"region\" class=\"adl-accordion__content\">\n            \n<p>To customize the position of the PIN input area on your mobile device screen in <a href=\"\/pt\/point-of-sale\/mobile-android\/understand#kiosk-mode\">kiosk mode<\/a> use <code>PinInputAlignment<\/code>. <\/p>\n<ul>\n<li>\n<p>Options are: <code>Left<\/code> or <code>Right<\/code> (default value).<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">Left<\/th>\n<th style=\"text-align: center;\">Right<\/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\/pin-Left-Portrait.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\/pin-Right-Portrait.svg?decoding=auto&amp;fetchpriority=auto\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"language-kotlin\">(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  kioskModeUiParameters = KioskModeUiParameters.create(\n     tapToPayKioskAnimation = TapToPayKioskAnimationType.directional(NfcDirectionalPosition.CenterLeft), \n     pinInputAlignment = PinInputAlignment.Right,\n  ),\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=\"#apply-kiosk-mode-on-all-smaller-tablets\">\n                                    <h4 class=\"adl-accordion__title\">Apply kiosk mode on all smaller tablets<\/h4>\n                            <\/div>\n        <\/div>\n        <div role=\"region\" class=\"adl-accordion__content\">\n            \n<p>To enable <a href=\"\/pt\/point-of-sale\/mobile-android\/understand#kiosk-mode\">kiosk mode<\/a> on all tablets with a screen width that is smaller than 9 inches, then you need to pass <code>applyToAllTablets = true<\/code> in your <code>KioskModeUiParameters<\/code> object. <\/p>\n<ul>\n<li>Possible values are:\n<ul>\n<li><strong>true<\/strong>: Globally enables kiosk mode on all tablets within this screen width range.<\/li>\n<li><strong>false<\/strong>: Disables global kiosk mode enforcement for tablets within this screen width range.\n\n        <\/div>\n    <\/div>\n<\/div>\n<\/li>\n<\/ul><\/li>\n<\/ul>\n<h2 id=\"payment\">6. 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 NFC reader on your mobile device. <\/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(TapToPay)<\/code>. <\/p>\n<pre><code class=\"language-kotlin\">val paymentInterface = InPersonPayments.getPaymentInterface(TapToPay)<\/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-android\/build\/tap-to-pay#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 and shows the transaction screen on your mobile device. <\/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\">7. 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\">8. 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>9. (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>9. (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 Tap&nbsp;to&nbsp;Pay 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=\"-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\/shopper-recognition\/tax-free-shopping\/\">Tax-free shopping<\/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<\/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:29%;\" 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:29%;\" 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:29%;\" 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><\/div>\n","url":"https:\/\/docs.adyen.com\/pt\/point-of-sale\/mobile-android\/build\/tap-to-pay","articleFields":{"description":"Integrate your Android POS app with the Mobile SDK to make Tap to Pay payments.","parameters":{"generic_sdk_name":"Mobile SDK","short_sdk_name":"Mobile SDK","sdk_name":"Mobile SDK for Android","solution_name":"Tap to Pay on Android","solution":"ttpAndroid","platform":"Android"},"type":"page","last_edit_on":"10-05-2023 21:46","feedback_component":true,"filters_component":false,"page_id":"b96946c7-4c39-4c86-a093-67139b774e8e","decision_tree":"[]"},"algolia":{"url":"https:\/\/docs.adyen.com\/pt\/point-of-sale\/mobile-android\/build\/tap-to-pay","title":"Tap to Pay on Android","content":"With our Tap to Pay on Android solution you can accept contactless in-person payments using an Android mobile device as the payment interface, and process these payments on the plataforma de pagamentos da Adyen.\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\nAn Android commercial off-the-shelf (COTS) mobile device with an integrated NFC reader. Must not be a payment terminal. 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 Tap to Pay on Android.\n\n\nSetup steps\nBefore you begin: Ask our Support Team  enable your Adyen test account for using our Mobile solutions.Order a test card.\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, 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. The SDK initializes automatically, but you can change that.\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 Mobile SDK.\nThe SDK initiates the transaction on the card reader.\nTo complete the payment, the customer taps the NFC reader on your mobile device 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 Mobile SDK initializes automatically, using the Android App Startup library. If you prefer to manually initialize the Mobile SDK, add the following code to the POS app's AndroidManifest.xml file to disable the Mobile SDK.\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 Mobile SDK 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 Mobile SDK 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 Mobile SDK 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 Mobile SDK 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. 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            \n                                    Customize position of the NFC tap indicator\n                            \n        \n        \n            \nThe default UI is designed for devices with the NFC antenna at the top rear. It shows an animation that points at the antenna's location on the back of the device. If the NFC antenna on your device is located in a different position, you can customize the position of the tap indicator on the mobile device screen. You need to identify the position of the device's NFC antenna and use tapToPayUiParameters. Options can be Directional to show a chevron-type arrow, pointing in the specified direction, or Front to a static image of an NFC logo.\n\nOptions for Directional are: TopCenter, or BottomCenter.\n\n\n\n\nTopCenter\nBottomCenter\n\n\n\n\n\n\n\n\n\n  (...)\n  merchantUiParameters = MerchantUiParameters.create(\n      tapToPayUiParameters = TapToPayUiParameters.create(\n          animation = TapToPayAnimationType.directional(NfcDirectionalPosition.BottomCenter),\n      ),\n      \/\/ ...\n  )\n\n\nOptions for Front are: TopCenter, Center, or BottomCenter.\n\n\n\nTopCenter\nCenter\nBottomCenter\n\n\n\n\n\n\n\n\n\n\n(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  tapToPayUiParameters = TapToPayUiParameters.create(\n      animation = TapToPayAnimationType.front(NfcFrontPosition.BottomCenter),\n  ),\n  \/\/ ...\n)\n\n\n\n        \n    \n\n \n\n    \n    \n        \n            \n            \n                                    Customize position of NFC tap indicator in kiosk mode\n                            \n        \n        \n            \nWhen in kiosk mode, the default position of the tap indicator is at the bottom-center of the device screen. You need to identify the position of your mobile device's NFC antenna to customize the position of the NFC tap indicator on your mobile device screen in kiosk mode. Then use TapToPayKioskAnimationType for placement options for the NFC tap indicator. The indicator can either be a static image of an NFC logo (Front) or an animated chevron-type arrow (Directional).\n\n\nOptions for Front are: TopCenter, Center, BottomCenter, LeftCenter, or RightCenter. \n\n\n\nTopCenter\nCenter\nBottomCenter\n\n\n\n\n\n\n\n\n\n\n\n\n\nLeftCenter\nRightCenter\n\n\n\n\n\n\n\n\n\n(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  kioskModeUiParameters = KioskModeUiParameters.create(\n     tapToPayKioskAnimation = TapToPayKioskAnimationType.front(NfcFrontPosition.TopCenter),\n  ),\n  \/\/ ...\n)\n\n\nOptions for Directional are: TopLeftFacingLeft, TopLeft, TopCenter, TopRight, TopRightFacingRight, CenterLeft, CenterRight, BottomLeftFacingLeft, BottomLeft, BottomCenter (default value), BottomRight, or BottomRightFacingRight.      \n\n\n\nTopLeft\nTopCenter\nTopRight\n\n\n\n\n\n\n\n\n\n\n\n\n\nBottomLeft\nBottomCenter\nBottomRight\n\n\n\n\n\n\n\n\n\n\n\n\n\nBottomLeftFacingLeft\nTopRightFacingRight\nBottomRightFacingRight\n\n\n\n\n\n\n\n\n\n\n\n\n\nTopLeftFacingLeft\nCenterLeft\nCenterRight\n\n\n\n\n\n\n\n\n\n\n(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  kioskModeUiParameters = KioskModeUiParameters.create(\n      tapToPayKioskAnimation = TapToPayKioskAnimationType.directional(NfcDirectionalPosition.CenterLeft),\n  ),\n  \/\/ ...\n)\n\n\n\n        \n    \n\n\n\n    \n    \n        \n            \n            \n                                    Customize position of PIN input area in kiosk mode\n                            \n        \n        \n            \nTo customize the position of the PIN input area on your mobile device screen in kiosk mode use PinInputAlignment. \n\n\nOptions are: Left or Right (default value).\n\n\n\nLeft\nRight\n\n\n\n\n\n\n\n\n\n(...)\nmerchantUiParameters = MerchantUiParameters.create(\n  kioskModeUiParameters = KioskModeUiParameters.create(\n     tapToPayKioskAnimation = TapToPayKioskAnimationType.directional(NfcDirectionalPosition.CenterLeft), \n     pinInputAlignment = PinInputAlignment.Right,\n  ),\n  \/\/ ...\n)\n\n\n\n        \n    \n\n\n\n    \n    \n        \n            \n            \n                                    Apply kiosk mode on all smaller tablets\n                            \n        \n        \n            \nTo enable kiosk mode on all tablets with a screen width that is smaller than 9 inches, then you need to pass applyToAllTablets = true in your KioskModeUiParameters object. \n\nPossible values are:\n\ntrue: Globally enables kiosk mode on all tablets within this screen width range.\nfalse: Disables global kiosk mode enforcement for tablets within this screen width range.\n\n        \n    \n\n\n\n\n6. Handle a payment\nIn this step you add code to start a transaction with:\n\nA Terminal API payment request.\n\nThe NFC reader on your mobile device. \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(TapToPay). \nval paymentInterface = InPersonPayments.getPaymentInterface(TapToPay)\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 and shows the transaction screen on your mobile device. \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\n7. 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\n8. 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\n9. (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\n9. (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 Tap&nbsp;to&nbsp;Pay 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.\n","type":"page","locale":"pt","boost":16,"hierarchy":{"lvl0":"Home","lvl1":"Terminais","lvl2":"Android Mobile solutions","lvl3":"Build your Android Mobile solution","lvl4":"Tap to Pay on 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\/tap-to-pay"},"levels":5,"category":"In-person payments","category_color":"green","tags":["Android"]},"articleFiles":{"directional_bottomcenter.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/03.point-of-sale\/55.mobile-android\/06.build\/01.tap-to-pay\/directional_bottomcenter.png\" \/>","directional_topcenter.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/03.point-of-sale\/55.mobile-android\/06.build\/01.tap-to-pay\/directional_topcenter.png\" \/>","front_bottomcenter.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/03.point-of-sale\/55.mobile-android\/06.build\/01.tap-to-pay\/front_bottomcenter.png\" \/>","front_center.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/03.point-of-sale\/55.mobile-android\/06.build\/01.tap-to-pay\/front_center.png\" \/>","front_topcenter.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/03.point-of-sale\/55.mobile-android\/06.build\/01.tap-to-pay\/front_topcenter.png\" \/>"}}
