{"title":"Show a virtual receipt on the terminal","category":"default","creationDate":1741965420,"content":"<p>Before the payment transaction starts, you can use the payment terminal to show the shopper an overview of their purchase. You can also add a QR code to this virtual receipt.<\/p>\n<div class=\"notices blue\">\n<p>A request to show a virtual receipt doesn't time out. The terminal continues to show the receipt until you send another request. For example, a payment request, or a request to <a href=\"\/point-of-sale\/shopper-engagement\/display-data\/idle-display\">show the standby screen<\/a>.<\/p>\n<\/div>\n<h4>Without QR code<\/h4>\n<p>The next examples show what virtual receipts look like on landscape (wide) and portrait (narrow) terminal displays. The receipt lines are scrollable.<\/p>\n<div class=\"sc-columns\" style=\"columns:2 auto;-moz-columns:2 auto;column-gap:normal;-moz-column-gap:normal;\">\n<div>\n<div class=\"hint--right\" data-hint=\"Virtual receipt on landscape display\">\n<p><img alt=\"\" src=\"\/images\/7\/f\/d\/4\/0\/7fd40130a4f93696bfd0101843f4ea48ed13e070-screen-enlineitemlandscape.png\" \/><\/p>\n<\/div>\n<\/div>\n<div>\n<div class=\"hint--right\" data-hint=\"Virtual receipt on portrait display\">\n<p><img alt=\"\" src=\"\/images\/1\/7\/6\/b\/d\/176bd9ac0788401372cde304fc692cd3e117cd4a-screen-enlineitemportrait.png\" \/><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h4>With QR code<\/h4>\n<p>It is also possible to add a QR code. A terminal with a landscape display shows the QR code next to the receipt lines.<\/p>\n<div class=\"hint--right\" data-hint=\"QR code and virtual receipt on landscape display\">\n<p><img alt=\"\" src=\"\/images\/5\/9\/4\/d\/9\/594d99cefac23eae656eafba20dd40da8dd9d65a-screen-enlineitemplusqrcodelandscape.png\" \/><\/p>\n<\/div>\n<p>A terminal with a portrait display shows two screens. First a screen with the QR code and a button to proceed, and then a screen with the receipt lines.<\/p>\n<div class=\"sc-columns\" style=\"columns:2 auto;-moz-columns:2 auto;column-gap:normal;-moz-column-gap:normal;\">\n<div>\n<div class=\"hint--right\" data-hint=\"QR code before the virtual receipt\">\n<p><img alt=\"\" src=\"\/images\/b\/c\/b\/a\/d\/bcbad94f109d925638b3618545926ab3c93cea6c-screen-enqrcodebeforelineitemportrait.png\" \/>\u00a0<\/p>\n<\/div>\n<\/div>\n<div>\n<div class=\"hint--right\" data-hint=\"Virtual receipt after QR code\">\n<p><img alt=\"\" src=\"\/images\/1\/7\/6\/b\/d\/176bd9ac0788401372cde304fc692cd3e117cd4a-screen-enlineitemportrait.png\" \/><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2 id=\"virtual-receipt-xml\">Receipt XML file<\/h2>\n<p>To show a virtual receipt on the terminal display, you need to gather all content in an XML file, convert this file to a Base64 string, and pass that string in a display request.<\/p>\n<p>The XML file can contain:<\/p>\n<ul>\n<li><code>&lt;screen name&gt;<\/code>: the XSLT to use. This determines whether a QR code is added to the virtual receipt.<\/li>\n<li><code>&lt;image&gt;<\/code> : the image to show on the left part of the screen. This is only supported on SFO1 payment terminals. The image must be converted to a Base64-encoded string.<\/li>\n<li><code>&lt;qrcodeblock&gt;<\/code>: a QR code with a header and footer. When used with a <code>&lt;screen name&gt;<\/code> that doesn't support showing a QR code, the <code>&lt;qrcodeblock&gt;<\/code> is ignored.<\/li>\n<li><code>&lt;list-header&gt;<\/code>: the header line of the virtual receipt.<\/li>\n<li><code>&lt;lines&gt;<\/code>: contains line items that represent the goods that the shopper is purchasing. Each line item can have a <code>count<\/code>, <code>description<\/code>, and <code>amount<\/code>. The <code>amount<\/code> can have <code>currency<\/code> and <code>value<\/code>. On SFO1 terminals, each line can also have an <code>icon<\/code> and a <code>subtitle<\/code>.<\/li>\n<li><code>&lt;subtotal&gt;<\/code>: the amount due before discounts and taxes.<\/li>\n<li><code>&lt;tax&gt;<\/code>: total discounts, amount and type of taxes, total tax amount.<\/li>\n<li><code>&lt;total&gt;<\/code>: final amount due.<\/li>\n<\/ul>\n<p>Use the following example XML file to populate an XML input file with line items and total amounts from your POS app, making sure you specify a <code>&lt;screen name&gt;<\/code> that is compatible with the terminal and the result you want to achieve:<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">Effect<\/th>\n<th style=\"text-align: left;\"><code>&lt;screen name&gt;<\/code><\/th>\n<th style=\"text-align: left;\">Terminal model<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\">Receipt <strong>with<\/strong> QR code<\/td>\n<td style=\"text-align: left;\"><code>virtual-receipt-with-qr-code.xslt<\/code><\/td>\n<td style=\"text-align: left;\">All that support virtual receipts<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Receipt <strong>without<\/strong> QR code<\/td>\n<td style=\"text-align: left;\"><code>virtual-receipt.xslt<\/code><\/td>\n<td style=\"text-align: left;\">AMS1, e280, P400 Plus, S1E, S1F2, SFO1, V400c Plus, V400m<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><\/td>\n<td style=\"text-align: left;\"><code>virtual_receipt02.xslt<\/code><\/td>\n<td style=\"text-align: left;\">M400<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Receipt <strong>without<\/strong> QR code, receipt header not 'sticky'<\/td>\n<td style=\"text-align: left;\"><code>virtual_receipt01.xslt<\/code><\/td>\n<td style=\"text-align: left;\">M400<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Receipt <strong>without<\/strong> QR code, receipt header not 'sticky', receipt footer 'sticky', auto-scroll to the bottom<\/td>\n<td style=\"text-align: left;\"><code>virtual-receipt01.xslt<\/code><\/td>\n<td style=\"text-align: left;\">AMS1, S1E, S1F2, V400M, P400<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><\/td>\n<td style=\"text-align: left;\"><code>virtual_receipt03.xslt<\/code><\/td>\n<td style=\"text-align: left;\">M400<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"'Example XML file'\" :id=\"''\" :code-data='[{\"language\":\"xml\",\"tabTitle\":\"\",\"content\":\"&lt;?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?&gt;\\n&lt;screen name=\\\"virtual-receipt-with-qr-code.xslt\\\"&gt;\\n    <!-- If you do not want a QR code, use virtual_receipt01.xslt or virtual_receipt02.xslt for M400; or virtual-receipt.xslt for other terminals. If you want the auto-scroll, use virtual-receipt01.xslt for AMS1, S1E, S1F2, V400M, and P400; or virtual_receipt03.xslt for M400. -->\\n    &lt;receipt&gt;\\n    &lt;image&gt;\\\"iVBORw0KGgoAAAANS\\\"&lt;\\\/image&gt;\\n    <!-- Only on SFO1. To include the image, use virtual-receipt.xslt for the sreen name and the image tag. -->\\n        &lt;qrcodeblock&gt;\\n            &lt;qrheader&gt;\\n                &lt;description&gt;Scan to access member card&lt;\\\/description&gt;\\n            &lt;\\\/qrheader&gt;\\n            &lt;call-to-action&gt;Scan&lt;\\\/call-to-action&gt;\\n            &lt;qrcodedata&gt;https%3A%2F%2Fwww%2Eadyen%2Ecom%2Fsignup%2F%3Flocation%3Damsterdam%26store%3DStore42%26POSID%3DREG0042%26hash%3DAAhbcdfjkbckjwbnadsjkn4%3D&lt;\\\/qrcodedata&gt;\\n            &lt;qrfooter&gt;\\n                &lt;description&gt;Do not have the app? Scan to download&lt;\\\/description&gt;\\n            &lt;\\\/qrfooter&gt;\\n        &lt;\\\/qrcodeblock&gt;\\n        &lt;list-header&gt;Your items&lt;\\\/list-header&gt;\\n        <!-- a receipt can have 0 or 1 lines element -->\\n        &lt;lines&gt;\\n            <!-- the lines element can have 0 or more lineitems -->\\n            &lt;lineitem&gt;\\n                &lt;icon&gt;\\\"iVBORw0KGgoAAAANS\\\"&lt;\\\/icon&gt;\\n                <!-- icon can only be added on SFO1-->\\n                &lt;description&gt;** SALES **&lt;\\\/description&gt;\\n                &lt;subtitle&gt;Quantity: 1&lt;\\\/subtitle&gt;\\n                <!-- subtitle can only be added on SFO1-->\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                <!-- all elements (count, description, and amount) are optional -->\\n                &lt;count&gt;1&lt;\\\/count&gt;\\n                &lt;description&gt;Running shoes&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    <!-- an amount must have a currency symbol or code, and a value -->\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;79.99&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                &lt;count&gt;2&lt;\\\/count&gt;\\n                &lt;description&gt;Green T-shirt @ 9.89&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;19.78&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                &lt;description&gt;** RETURNS **&lt;\\\/description&gt;\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                &lt;count&gt;1&lt;\\\/count&gt;\\n                &lt;description&gt;Grey t-shirt @ 12.99&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;-12.99&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                &lt;description&gt;&lt;\\\/description&gt;<!-- a lineitem containing only an empty description returns a blank line -->\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                &lt;description&gt;** DISCOUNTS **&lt;\\\/description&gt;\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                &lt;description&gt;Loyalty discount&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;-4.48&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/lineitem&gt;\\n            &lt;lineitem&gt;\\n                &lt;description&gt;____________________&lt;\\\/description&gt;\\n            &lt;\\\/lineitem&gt;\\n            <!-- an empty lineitem returns a blank line (taking up vertical space) -->\\n            &lt;lineitem&gt;&lt;\\\/lineitem&gt;\\n        &lt;\\\/lines&gt;\\n        <!-- a receipt can have 0 or 1 subtotal element -->\\n        &lt;subtotal&gt;\\n            <!-- description and amount are both optional -->\\n            &lt;description&gt;Subtotal&lt;\\\/description&gt;\\n            &lt;amount&gt;\\n                &lt;currency&gt;$&lt;\\\/currency&gt;\\n                &lt;value&gt;86.78&lt;\\\/value&gt;\\n            &lt;\\\/amount&gt;\\n        &lt;\\\/subtotal&gt;\\n        <!-- a receipt can have 0 or 1 tax element -->\\n        &lt;tax&gt;\\n            <!-- tax element can have 0 or 1 totaldiscount element-->\\n            &lt;totaldiscount&gt;\\n                &lt;description&gt;Total discount:&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;-4.48&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/totaldiscount&gt;\\n            <!-- tax element can have 0 or more taxitem elements -->\\n            &lt;taxitem&gt;\\n                <!-- description and amount are both optional -->\\n                &lt;description&gt;State tax:&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;5.97&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/taxitem&gt;\\n            &lt;taxitem&gt;\\n                &lt;description&gt;County tax:&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;1.85&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/taxitem&gt;\\n            <!-- tax element can have 0 or 1 taxtotal element -->\\n            &lt;taxtotal&gt;\\n                <!-- description and amount are both optional -->\\n                &lt;description&gt;Total tax:&lt;\\\/description&gt;\\n                &lt;amount&gt;\\n                    &lt;currency&gt;$&lt;\\\/currency&gt;\\n                    &lt;value&gt;7.82&lt;\\\/value&gt;\\n                &lt;\\\/amount&gt;\\n            &lt;\\\/taxtotal&gt;\\n        &lt;\\\/tax&gt;\\n        <!-- a receipt can have 0 or 1 total element -->\\n        &lt;total&gt;\\n            <!-- description and amount are both optional -->\\n            &lt;description&gt;Total amount:&lt;\\\/description&gt;\\n            &lt;amount&gt;\\n                &lt;currency&gt;$&lt;\\\/currency&gt;\\n                &lt;value&gt;90.12&lt;\\\/value&gt;\\n            &lt;\\\/amount&gt;\\n        &lt;\\\/total&gt;\\n    &lt;\\\/receipt&gt;\\n&lt;\\\/screen&gt;\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<div class=\"notices green\">\n<p>On the terminal screen, the currency symbol only shows for the total amount.<\/p>\n<\/div>\n<h2 id=\"display-virtual-receipt\">Make a display request for a virtual receipt<\/h2>\n<ol>\n<li>\n<p>Create the virtual receipt:<\/p>\n<ol>\n<li>\n<p>Based on our <a href=\"#virtual-receipt-xml\">example XML file<\/a>, populate an XML file with line items and total amounts from your POS app. Make sure that you use the correct screen name:<\/p>\n<ul>\n<li><code>&lt;screen name=\"virtual-receipt.xslt\"&gt;<\/code>: shows a receipt without QR code where the receipt has a 'sticky' header which remains visible when scrolling down the receipt lines. For use on portrait terminals: <span translate=\"no\"><strong>AMS1<\/strong><\/span>, <span translate=\"no\"><strong>e280<\/strong><\/span>, <span translate=\"no\"><strong>P400 Plus<\/strong><\/span>, <span translate=\"no\"><strong>S1E<\/strong><\/span>, <span translate=\"no\"><strong>S1F2<\/strong><\/span>, <span translate=\"no\"><strong>V400c Plus<\/strong><\/span>, and <span translate=\"no\"><strong>V400m<\/strong><\/span>.<\/li>\n<li><code>&lt;screen name=\"virtual-receipt-with-qr-code.xslt\"&gt;<\/code>: shows a receipt with a QR code. For use on any terminal model that supports virtual receipts.<\/li>\n<li><code>&lt;screen name=\"virtual_receipt01.xslt\"&gt;<\/code>: shows a receipt without QR code. For use on the <span translate=\"no\"><strong>M400<\/strong><\/span>.<\/li>\n<li><code>&lt;screen name=\"virtual_receipt02.xslt\"&gt;<\/code>: shows a receipt without QR code but with a 'sticky' header. For use on the <span translate=\"no\"><strong>M400<\/strong><\/span>.<\/li>\n<li><code>&lt;screen name=\"virtual-receipt01.xslt\"&gt;<\/code>: shows a receipt without QR code, a 'sticky' footer, and auto-scroll to the bottom. For use on the <span translate=\"no\"><strong>AMS1<\/strong><\/span>, <span translate=\"no\"><strong>S1E<\/strong><\/span>, <span translate=\"no\"><strong>S1F2<\/strong><\/span>, <span translate=\"no\"><strong>SFO1<\/strong><\/span>, <span translate=\"no\"><strong>V400M<\/strong><\/span> and <span translate=\"no\"><strong>P400<\/strong><\/span>.<\/li>\n<li><code>&lt;screen name=\"virtual_receipt03.xslt\"&gt;<\/code>: shows a receipt without QR code, a 'sticky' footer, and auto-scroll to the bottom. For use on the <span translate=\"no\"><strong>M400<\/strong><\/span>.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Convert the XML content to a Base64 string.<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p>Make a <a href=\"\/point-of-sale\/design-your-integration\/terminal-api\">Terminal API<\/a> display request, specifying:<\/p>\n<ul>\n<li>\n<p>The standard <a href=\"\/point-of-sale\/design-your-integration\/terminal-api#request-message-header\">\n  <code>SaleToPOIRequest.MessageHeader<\/code>\n<\/a> object, with <code>MessageClass<\/code> set to <span translate=\"no\"><strong>Device<\/strong><\/span> and <code>MessageCategory<\/code> set to <span translate=\"no\"><strong>Display<\/strong><\/span>.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">Parameter<\/th>\n<th style=\"text-align: center;\">Required<\/th>\n<th style=\"text-align: left;\">Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\"><code>ProtocolVersion<\/code><\/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<td style=\"text-align: left;\"><strong>3.0<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>MessageClass<\/code><\/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<td style=\"text-align: left;\"><span translate=\"no\"><strong>Device<\/strong><\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>MessageCategory<\/code><\/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<td style=\"text-align: left;\"><span translate=\"no\"><strong>Display<\/strong><\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>MessageType<\/code><\/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<td style=\"text-align: left;\"><span translate=\"no\"><strong>Request<\/strong><\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>ServiceID<\/code><\/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<td style=\"text-align: left;\">Your unique ID for this request, consisting of 1-10 alphanumeric characters. Must be unique within the last 48 hours for the terminal (<code>POIID<\/code>) being used.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>SaleID<\/code><\/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<td style=\"text-align: left;\">Your unique ID for the POS system component to send this request from.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>POIID<\/code><\/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<td style=\"text-align: left;\">The unique ID of the terminal to send this request to. Format: <em>[device model]-[serial number]<\/em>.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>The  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/terminal-api\/latest\/post\/display#request-DisplayOutput\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DisplayRequest.DisplayOutput<\/a> array containing a single array item with:<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">Parameter<\/th>\n<th style=\"text-align: left;\">Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\"><code>Device<\/code><\/td>\n<td style=\"text-align: left;\"><span translate=\"no\"><strong>CustomerDisplay<\/strong><\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>InfoQualify<\/code><\/td>\n<td style=\"text-align: left;\"><span translate=\"no\"><strong>Display<\/strong><\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>OutputContent.OutputFormat<\/code><\/td>\n<td style=\"text-align: left;\"><span translate=\"no\"><strong>XHTML<\/strong><\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><code>OutputContent.OutputXHTML<\/code><\/td>\n<td style=\"text-align: left;\">The Base64 string containing the XML content.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/li>\n<\/ul>\n<div data-component-wrapper=\"code-sample\">\n<code-sample :title=\"''\" :id=\"'display-virtual-receipts_0'\" :code-data='[{\"language\":\"json\",\"tabTitle\":\"JSON\",\"content\":\"{\\n   \\\"SaleToPOIRequest\\\":{\\n      \\\"DisplayRequest\\\":{\\n         \\\"DisplayOutput\\\":[\\n            {\\n               \\\"Device\\\":\\\"CustomerDisplay\\\",\\n               \\\"InfoQualify\\\":\\\"Display\\\",\\n               \\\"OutputContent\\\":{\\n                  \\\"OutputFormat\\\":\\\"XHTML\\\",\\n                  \\\"OutputXHTML\\\": \\\"...paste Base64 encoded XML here...\\\"\\n               }\\n            }\\n         ]\\n      },\\n      \\\"MessageHeader\\\":{\\n         \\\"ServiceID\\\":\\\"1116172359\\\",\\n         \\\"ProtocolVersion\\\":\\\"3.0\\\",\\n         \\\"MessageClass\\\":\\\"Device\\\",\\n         \\\"POIID\\\":\\\"M400-284251175\\\",\\n         \\\"MessageType\\\":\\\"Request\\\",\\n         \\\"SaleID\\\":\\\"POSSystemID12345\\\",\\n         \\\"MessageCategory\\\":\\\"Display\\\"\\n      }\\n   }\\n}\"},{\"language\":\"java\",\"tabTitle\":\"Java\",\"content\":\"String serviceID = \\\"YOUR_UNIQUE_ATTEMPT_ID\\\";\\nString POIID = \\\"YOUR_TERMINAL_ID\\\";\\nString saleID = \\\"YOUR_CASH_REGISTER_ID\\\";\\n\\nSaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest();\\nDisplayRequest displayRequest = new DisplayRequest();\\nDisplayOutput displayOutput = new DisplayOutput();\\ndisplayOutput.setDevice( DeviceType.CUSTOMER_DISPLAY );\\ndisplayOutput.setInfoQualify( InfoQualifyType.DISPLAY );\\nOutputContent outputContent = new OutputContent();\\noutputContent.setOutputFormat( OutputFormatType.XHTML );\\noutputContent.setOutputXHTML(\\\"...paste base64 encoded XML here...\\\");\\ndisplayOutput.setOutputContent(outputContent);\\ndisplayRequest.setDisplayOutput(displayOutput);\\nsaleToPOIRequest.setDisplayRequest(displayRequest);\\n\\nMessageHeader messageHeader = new MessageHeader();\\nmessageHeader.setServiceID(serviceID);\\nmessageHeader.setProtocolVersion(\\\"3.0\\\");\\nmessageHeader.setMessageClass( MessageClassType.DEVICE );\\nmessageHeader.setPOIID(POIID);\\nmessageHeader.setMessageType( MessageType.REQUEST );\\nmessageHeader.setSaleID(saleID);\\nmessageHeader.setMessageCategory( MessageCategoryType.DISPLAY );\\nsaleToPOIRequest.setMessageHeader(messageHeader);\\nterminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<\/li>\n<li>\n<p>In the display response, check the  <a href=\"https:\/\/docs.adyen.com\/api-explorer\/terminal-api\/latest\/post\/display#responses-200-OutputResult\" class=\"codeLabel  external-link no-image\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">OutputResult<\/a>.<br \/>\nIf the request is successful, this includes <code>Response.Result<\/code>: <span translate=\"no\"><strong>Success<\/strong><\/span>.<\/p>\n<div data-component-wrapper=\"code-sample\">\n<code-sample :title=\"'Display response'\" :id=\"''\" :code-data='[{\"language\":\"json\",\"tabTitle\":\"\",\"content\":\"{\\n   \\\"SaleToPOIResponse\\\":{\\n      \\\"DisplayResponse\\\":{\\n         \\\"OutputResult\\\":[\\n            {\\n               \\\"InfoQualify\\\":\\\"Display\\\",\\n               \\\"Device\\\":\\\"CustomerDisplay\\\",\\n               \\\"Response\\\":{\\n                  \\\"Result\\\":\\\"Success\\\"\\n               }\\n            }\\n         ]\\n      },\\n      \\\"MessageHeader\\\":{...}\\n   }\\n}\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>If the request is not successful, the <code>DisplayResponse.OutputResult<\/code> includes:<\/p>\n<ul>\n<li><code>Response.Result<\/code>: <span translate=\"no\"><strong>Failure<\/strong><\/span>.<\/li>\n<li><code>AdditionalResponse<\/code> and <code>ErrorCondition<\/code>: more information about why the request failed.<\/li>\n<\/ul>\n<p>See <a href=\"#validation\">XML validation<\/a> for information about how errors in the XML content are reported.<br \/>\nThe next example shows the response after sending the display request to an incompatible terminal.<\/p>\n<div data-component-wrapper=\"code-sample\">\n<code-sample :title=\"'Response for a failed display request'\" :id=\"''\" :code-data='[{\"language\":\"json\",\"tabTitle\":\"\",\"content\":\"{\\n   \\\"SaleToPOIResponse\\\":{\\n      \\\"DisplayResponse\\\":{\\n         \\\"OutputResult\\\":[\\n            {\\n               \\\"Device\\\":\\\"CustomerDisplay\\\",\\n               \\\"InfoQualify\\\":\\\"Display\\\",\\n               \\\"Response\\\":{\\n                  \\\"Result\\\":\\\"Failure\\\",\\n                  \\\"AdditionalResponse\\\":\\\"message=DisplayRequest%20API%20cannot%20be%20used%20for%20this%20terminal%20model.\\\",\\n                  \\\"ErrorCondition\\\":\\\"NotAllowed\\\"\\n               }\\n            }\\n         ]\\n      },\\n      \\\"MessageHeader\\\":{...}\\n   }\\n}\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<\/li>\n<\/ol>\n<h2 id=\"validation\">XML validation<\/h2>\n<p>When we receive your display request for a virtual receipt, we check whether we can parse the XML content. We can also check whether the XML content matches the XML Schema Definition (XSD). We only do this XSD check if it is enabled for your account.<\/p>\n<ul>\n<li>\n<p><strong>Parsing<\/strong><br \/>\nWe always check whether we can parse the XML content of your request.<\/p>\n<p>For example, if the XML contains a syntax error like a missing caret <code>&gt;<\/code>, we cannot parse the XML. You receive a failure response with <em>XHTML data could not be parsed<\/em>.<\/p>\n<div data-component-wrapper=\"code-sample\">\n<code-sample :title=\"'XHTML data could not be parsed'\" :id=\"''\" :code-data='[{\"language\":\"json\",\"tabTitle\":\"\",\"content\":\"\\t{\\n\\t\\t...\\n\\t\\t\\\"Response\\\": {\\n\\t\\t\\t\\\"AdditionalResponse\\\": \\\"message=XHTML%20data%20could%20not%20be%20parsed.\\\",\\n\\t\\t\\t \\\"ErrorCondition\\\": \\\"MessageFormat\\\",\\n\\t\\t\\t \\\"Result\\\": \\\"Failure\\\"\\n\\t\\t}\\n\\t}\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<\/li>\n<li>\n<p><strong>XSD<\/strong><br \/>\nIf we can parse the XML content and XSD checking is enabled, we validate the XML against the XSD.<\/p>\n<div class=\"notices yellow\">\n<p>To use this validation, ask our <a href=\"https:\/\/ca-test.adyen.com\/ca\/ca\/contactUs\/support.shtml?form=other\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Support Team<\/a> to enable the virtual receipt XSD check.<\/p>\n<\/div>\n<p>For example, if you add an element that is not in the XSD or if you omit a required element, the XML doesn't match the XSD. You receive a failure response with <em>XSD validation failed<\/em>.<\/p>\n<div data-component-wrapper=\"code-sample\">\n<code-sample :title=\"'XSD validation failed'\" :id=\"''\" :code-data='[{\"language\":\"json\",\"tabTitle\":\"\",\"content\":\"\\t{\\n\\t\\t...\\n\\t\\t\\\"Response\\\": {\\n\\t\\t\\t\\\"AdditionalResponse\\\": \\\"message=XSD%20validation%20failed.\\\",\\n\\t\\t\\t \\\"ErrorCondition\\\": \\\"MessageFormat\\\",\\n\\t\\t\\t \\\"Result\\\": \\\"Failure\\\"\\n\\t\\t}\\n\\t}\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>The details of any XSD errors are in the terminal log.<\/p>\n<\/li>\n<\/ul>\n<h2>See also<\/h2>\n<div class=\"see-also-links output-inline\" id=\"see-also\">\n<ul><li><a href=\"\/point-of-sale\/shopper-engagement\/display-data\/idle-display\"\n                        target=\"_self\"\n                        >\n                    Set the display to standby\n                <\/a><\/li><li><a href=\"\/point-of-sale\/shopper-engagement\/display-data\/display-qr-code\"\n                        target=\"_self\"\n                        >\n                    Show a QR code on the display\n                <\/a><\/li><li><a href=\"\/point-of-sale\/shopper-engagement\/display-data\/display-image\"\n                        target=\"_self\"\n                        >\n                    Show an image on the display\n                <\/a><\/li><\/ul><\/div>\n","url":"https:\/\/docs.adyen.com\/point-of-sale\/shopper-engagement\/display-data\/display-receipt","articleFields":{"description":"Show a virtual receipt on the display of the payment terminal.","feedback_component":true,"filters_component":false,"decision_tree":"[]","page_id":"8d3efd17-9285-4f53-bb3e-846eab85158f","last_edit_on":"14-03-2025 16:17"},"algolia":{"url":"https:\/\/docs.adyen.com\/point-of-sale\/shopper-engagement\/display-data\/display-receipt","title":"Show a virtual receipt on the terminal","content":"Before the payment transaction starts, you can use the payment terminal to show the shopper an overview of their purchase. You can also add a QR code to this virtual receipt.\n\nA request to show a virtual receipt doesn't time out. The terminal continues to show the receipt until you send another request. For example, a payment request, or a request to show the standby screen.\n\nWithout QR code\nThe next examples show what virtual receipts look like on landscape (wide) and portrait (narrow) terminal displays. The receipt lines are scrollable.\n\n\n\n\n\n\n\n\n\n\n\n\nWith QR code\nIt is also possible to add a QR code. A terminal with a landscape display shows the QR code next to the receipt lines.\n\n\n\nA terminal with a portrait display shows two screens. First a screen with the QR code and a button to proceed, and then a screen with the receipt lines.\n\n\n\n\u00a0\n\n\n\n\n\n\n\n\nReceipt XML file\nTo show a virtual receipt on the terminal display, you need to gather all content in an XML file, convert this file to a Base64 string, and pass that string in a display request.\nThe XML file can contain:\n\n&lt;screen name&gt;: the XSLT to use. This determines whether a QR code is added to the virtual receipt.\n&lt;image&gt; : the image to show on the left part of the screen. This is only supported on SFO1 payment terminals. The image must be converted to a Base64-encoded string.\n&lt;qrcodeblock&gt;: a QR code with a header and footer. When used with a &lt;screen name&gt; that doesn't support showing a QR code, the &lt;qrcodeblock&gt; is ignored.\n&lt;list-header&gt;: the header line of the virtual receipt.\n&lt;lines&gt;: contains line items that represent the goods that the shopper is purchasing. Each line item can have a count, description, and amount. The amount can have currency and value. On SFO1 terminals, each line can also have an icon and a subtitle.\n&lt;subtotal&gt;: the amount due before discounts and taxes.\n&lt;tax&gt;: total discounts, amount and type of taxes, total tax amount.\n&lt;total&gt;: final amount due.\n\nUse the following example XML file to populate an XML input file with line items and total amounts from your POS app, making sure you specify a &lt;screen name&gt; that is compatible with the terminal and the result you want to achieve:\n\n\n\nEffect\n&lt;screen name&gt;\nTerminal model\n\n\n\n\nReceipt with QR code\nvirtual-receipt-with-qr-code.xslt\nAll that support virtual receipts\n\n\nReceipt without QR code\nvirtual-receipt.xslt\nAMS1, e280, P400 Plus, S1E, S1F2, SFO1, V400c Plus, V400m\n\n\n\nvirtual_receipt02.xslt\nM400\n\n\nReceipt without QR code, receipt header not 'sticky'\nvirtual_receipt01.xslt\nM400\n\n\nReceipt without QR code, receipt header not 'sticky', receipt footer 'sticky', auto-scroll to the bottom\nvirtual-receipt01.xslt\nAMS1, S1E, S1F2, V400M, P400\n\n\n\nvirtual_receipt03.xslt\nM400\n\n\n\n\n    ","type":"page","locale":"en","boost":16,"hierarchy":{"lvl0":"Home","lvl1":"In-person payments","lvl2":"Shopper engagement","lvl3":"Display data on the terminal","lvl4":"Show a virtual receipt on the terminal"},"hierarchy_url":{"lvl0":"https:\/\/docs.adyen.com\/","lvl1":"https:\/\/docs.adyen.com\/point-of-sale","lvl2":"https:\/\/docs.adyen.com\/point-of-sale\/shopper-engagement","lvl3":"https:\/\/docs.adyen.com\/point-of-sale\/shopper-engagement\/display-data","lvl4":"\/point-of-sale\/shopper-engagement\/display-data\/display-receipt"},"levels":5,"category":"In-person payments","category_color":"green","tags":["virtual","receipt","terminal"]},"articleFiles":{"screen-EN_LineItem_landscape.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/images\/2\/1\/4\/c\/8\/214c861f6b57f0379ece85278a1e296170c26eab-screen-enlineitemlandscape.png\" \/>","screen-EN_LineItem_plus_QRCode_landscape.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/images\/4\/f\/0\/c\/2\/4f0c2ea331d32857907fa49c7fcf16e89f78f7c2-screen-enlineitemplusqrcodelandscape.png\" \/>","screen-EN_LineItem_portrait.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/images\/f\/9\/3\/6\/3\/f93636accfac8f099fdf875e7e8841b791e65c2d-screen-enlineitemportrait.png\" \/>","screen-EN_QRCode_before_LineItem_portrait.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/images\/f\/f\/0\/0\/7\/ff007ee7c48a38488fe139fc6b4b70a95b40fa8d-screen-enqrcodebeforelineitemportrait.png\" \/>","display-virtual-receipts_0.json":"<p alt=\"\">display-virtual-receipts_0.json<\/p>"}}
